refactor: dedupe acp binding helpers

This commit is contained in:
Peter Steinberger
2026-04-06 18:44:27 +01:00
parent 33cdb342cb
commit d9f21433a8

View File

@@ -35,7 +35,10 @@ import { updateSessionStore } from "../../../config/sessions.js";
import type { SessionAcpMeta } from "../../../config/sessions/types.js";
import {
getSessionBindingService,
type ConversationRef,
type SessionBindingPlacement,
type SessionBindingRecord,
type SessionBindingService,
} from "../../../infra/outbound/session-binding-service.js";
import type { CommandHandlerResult, HandleCommandsParams } from "../commands-types.js";
import {
@@ -92,6 +95,90 @@ async function resolveBoundReplyChannelData(params: {
return resolved ?? undefined;
}
function buildSpawnedAcpBindingMetadata(params: {
cfg: OpenClawConfig;
channel: string;
accountId: string;
sessionKey: string;
agentId: string;
label: string;
senderId: string;
sessionMeta?: SessionAcpMeta;
}): Record<string, unknown> {
return {
threadName: resolveThreadBindingThreadName({
agentId: params.agentId,
label: params.label,
}),
agentId: params.agentId,
label: params.label,
boundBy: params.senderId || "unknown",
introText: resolveThreadBindingIntroText({
agentId: params.agentId,
label: params.label,
idleTimeoutMs: resolveThreadBindingIdleTimeoutMsForChannel({
cfg: params.cfg,
channel: params.channel,
accountId: params.accountId,
}),
maxAgeMs: resolveThreadBindingMaxAgeMsForChannel({
cfg: params.cfg,
channel: params.channel,
accountId: params.accountId,
}),
sessionCwd: resolveAcpSessionCwd(params.sessionMeta),
sessionDetails: resolveAcpThreadSessionDetailLines({
sessionKey: params.sessionKey,
meta: params.sessionMeta,
}),
}),
};
}
async function bindSpawnedAcpSession(params: {
bindingService: SessionBindingService;
sessionKey: string;
conversationRef: ConversationRef;
placement: SessionBindingPlacement;
cfg: OpenClawConfig;
channel: string;
accountId: string;
agentId: string;
label: string;
senderId: string;
sessionMeta?: SessionAcpMeta;
bindError: string;
}): Promise<{ ok: true; binding: SessionBindingRecord } | { ok: false; error: string }> {
try {
const binding = await params.bindingService.bind({
targetSessionKey: params.sessionKey,
targetKind: "session",
conversation: params.conversationRef,
placement: params.placement,
metadata: buildSpawnedAcpBindingMetadata({
cfg: params.cfg,
channel: params.channel,
accountId: params.accountId,
sessionKey: params.sessionKey,
agentId: params.agentId,
label: params.label,
senderId: params.senderId,
sessionMeta: params.sessionMeta,
}),
});
return {
ok: true,
binding,
};
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return {
ok: false,
error: message || params.bindError,
};
}
}
async function bindSpawnedAcpSessionToCurrentConversation(params: {
commandParams: HandleCommandsParams;
sessionKey: string;
@@ -188,53 +275,20 @@ async function bindSpawnedAcpSessionToCurrentConversation(params: {
}
const label = params.label || params.agentId;
try {
const binding = await bindingService.bind({
targetSessionKey: params.sessionKey,
targetKind: "session",
conversation: conversationRef,
placement: "current",
metadata: {
threadName: resolveThreadBindingThreadName({
agentId: params.agentId,
label,
}),
agentId: params.agentId,
label,
boundBy: senderId || "unknown",
introText: resolveThreadBindingIntroText({
agentId: params.agentId,
label,
idleTimeoutMs: resolveThreadBindingIdleTimeoutMsForChannel({
cfg: params.commandParams.cfg,
channel: bindingPolicy.channel,
accountId: bindingPolicy.accountId,
}),
maxAgeMs: resolveThreadBindingMaxAgeMsForChannel({
cfg: params.commandParams.cfg,
channel: bindingPolicy.channel,
accountId: bindingPolicy.accountId,
}),
sessionCwd: resolveAcpSessionCwd(params.sessionMeta),
sessionDetails: resolveAcpThreadSessionDetailLines({
sessionKey: params.sessionKey,
meta: params.sessionMeta,
}),
}),
},
});
return {
ok: true,
binding,
};
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return {
ok: false,
error:
message || `Failed to bind the current ${channel} conversation to the new ACP session.`,
};
}
return bindSpawnedAcpSession({
bindingService,
sessionKey: params.sessionKey,
conversationRef,
placement: "current",
cfg: params.commandParams.cfg,
channel: bindingPolicy.channel,
accountId: bindingPolicy.accountId,
agentId: params.agentId,
label,
senderId,
sessionMeta: params.sessionMeta,
bindError: `Failed to bind the current ${channel} conversation to the new ACP session.`,
});
}
async function bindSpawnedAcpSessionToThread(params: {
@@ -369,53 +423,20 @@ async function bindSpawnedAcpSessionToThread(params: {
}
const label = params.label || params.agentId;
try {
const binding = await bindingService.bind({
targetSessionKey: params.sessionKey,
targetKind: "session",
conversation: conversationRef,
placement,
metadata: {
threadName: resolveThreadBindingThreadName({
agentId: params.agentId,
label,
}),
agentId: params.agentId,
label,
boundBy: senderId || "unknown",
introText: resolveThreadBindingIntroText({
agentId: params.agentId,
label,
idleTimeoutMs: resolveThreadBindingIdleTimeoutMsForChannel({
cfg: commandParams.cfg,
channel: spawnPolicy.channel,
accountId: spawnPolicy.accountId,
}),
maxAgeMs: resolveThreadBindingMaxAgeMsForChannel({
cfg: commandParams.cfg,
channel: spawnPolicy.channel,
accountId: spawnPolicy.accountId,
}),
sessionCwd: resolveAcpSessionCwd(params.sessionMeta),
sessionDetails: resolveAcpThreadSessionDetailLines({
sessionKey: params.sessionKey,
meta: params.sessionMeta,
}),
}),
},
});
return {
ok: true,
binding,
};
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return {
ok: false,
error: message || `Failed to bind a ${channel} thread/conversation to the new ACP session.`,
};
}
return bindSpawnedAcpSession({
bindingService,
sessionKey: params.sessionKey,
conversationRef,
placement,
cfg: commandParams.cfg,
channel: spawnPolicy.channel,
accountId: spawnPolicy.accountId,
agentId: params.agentId,
label,
senderId,
sessionMeta: params.sessionMeta,
bindError: `Failed to bind a ${channel} thread/conversation to the new ACP session.`,
});
}
async function cleanupFailedSpawn(params: {