mirror of https://github.com/openclaw/openclaw.git
refactor: share tlon outbound send context
This commit is contained in:
parent
a57c590a71
commit
407d0d296d
|
|
@ -153,6 +153,48 @@ function applyTlonSetupConfig(params: {
|
|||
};
|
||||
}
|
||||
|
||||
type ResolvedTlonAccount = ReturnType<typeof resolveTlonAccount>;
|
||||
|
||||
function resolveOutboundContext(params: { cfg: OpenClawConfig; accountId?: string; to: string }) {
|
||||
const account = resolveTlonAccount(params.cfg, params.accountId ?? undefined);
|
||||
if (!account.configured || !account.ship || !account.url || !account.code) {
|
||||
throw new Error("Tlon account not configured");
|
||||
}
|
||||
|
||||
const parsed = parseTlonTarget(params.to);
|
||||
if (!parsed) {
|
||||
throw new Error(`Invalid Tlon target. Use ${formatTargetHint()}`);
|
||||
}
|
||||
|
||||
return { account, parsed };
|
||||
}
|
||||
|
||||
function resolveReplyId(replyToId?: string, threadId?: string) {
|
||||
return (replyToId ?? threadId) ? String(replyToId ?? threadId) : undefined;
|
||||
}
|
||||
|
||||
async function withHttpPokeAccountApi<T>(
|
||||
account: ResolvedTlonAccount & { ship: string; url: string; code: string },
|
||||
run: (api: Awaited<ReturnType<typeof createHttpPokeApi>>) => Promise<T>,
|
||||
) {
|
||||
const api = await createHttpPokeApi({
|
||||
url: account.url,
|
||||
ship: account.ship,
|
||||
code: account.code,
|
||||
allowPrivateNetwork: account.allowPrivateNetwork ?? undefined,
|
||||
});
|
||||
|
||||
try {
|
||||
return await run(api);
|
||||
} finally {
|
||||
try {
|
||||
await api.delete();
|
||||
} catch {
|
||||
// ignore cleanup errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tlonOutbound: ChannelOutboundAdapter = {
|
||||
deliveryMode: "direct",
|
||||
textChunkLimit: 10000,
|
||||
|
|
@ -170,25 +212,8 @@ const tlonOutbound: ChannelOutboundAdapter = {
|
|||
return { ok: true, to: parsed.nest };
|
||||
},
|
||||
sendText: async ({ cfg, to, text, accountId, replyToId, threadId }) => {
|
||||
const account = resolveTlonAccount(cfg, accountId ?? undefined);
|
||||
if (!account.configured || !account.ship || !account.url || !account.code) {
|
||||
throw new Error("Tlon account not configured");
|
||||
}
|
||||
|
||||
const parsed = parseTlonTarget(to);
|
||||
if (!parsed) {
|
||||
throw new Error(`Invalid Tlon target. Use ${formatTargetHint()}`);
|
||||
}
|
||||
|
||||
// Use HTTP-only poke (no EventSource) to avoid conflicts with monitor's SSE connection
|
||||
const api = await createHttpPokeApi({
|
||||
url: account.url,
|
||||
ship: account.ship,
|
||||
code: account.code,
|
||||
allowPrivateNetwork: account.allowPrivateNetwork ?? undefined,
|
||||
});
|
||||
|
||||
try {
|
||||
const { account, parsed } = resolveOutboundContext({ cfg, accountId, to });
|
||||
return withHttpPokeAccountApi(account, async (api) => {
|
||||
const fromShip = normalizeShip(account.ship);
|
||||
if (parsed.kind === "dm") {
|
||||
return await sendDm({
|
||||
|
|
@ -198,33 +223,18 @@ const tlonOutbound: ChannelOutboundAdapter = {
|
|||
text,
|
||||
});
|
||||
}
|
||||
const replyId = (replyToId ?? threadId) ? String(replyToId ?? threadId) : undefined;
|
||||
return await sendGroupMessage({
|
||||
api,
|
||||
fromShip,
|
||||
hostShip: parsed.hostShip,
|
||||
channelName: parsed.channelName,
|
||||
text,
|
||||
replyToId: replyId,
|
||||
replyToId: resolveReplyId(replyToId, threadId),
|
||||
});
|
||||
} finally {
|
||||
try {
|
||||
await api.delete();
|
||||
} catch {
|
||||
// ignore cleanup errors
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
sendMedia: async ({ cfg, to, text, mediaUrl, accountId, replyToId, threadId }) => {
|
||||
const account = resolveTlonAccount(cfg, accountId ?? undefined);
|
||||
if (!account.configured || !account.ship || !account.url || !account.code) {
|
||||
throw new Error("Tlon account not configured");
|
||||
}
|
||||
|
||||
const parsed = parseTlonTarget(to);
|
||||
if (!parsed) {
|
||||
throw new Error(`Invalid Tlon target. Use ${formatTargetHint()}`);
|
||||
}
|
||||
const { account, parsed } = resolveOutboundContext({ cfg, accountId, to });
|
||||
|
||||
// Configure the API client for uploads
|
||||
configureClient({
|
||||
|
|
@ -235,15 +245,7 @@ const tlonOutbound: ChannelOutboundAdapter = {
|
|||
});
|
||||
|
||||
const uploadedUrl = mediaUrl ? await uploadImageFromUrl(mediaUrl) : undefined;
|
||||
|
||||
const api = await createHttpPokeApi({
|
||||
url: account.url,
|
||||
ship: account.ship,
|
||||
code: account.code,
|
||||
allowPrivateNetwork: account.allowPrivateNetwork ?? undefined,
|
||||
});
|
||||
|
||||
try {
|
||||
return withHttpPokeAccountApi(account, async (api) => {
|
||||
const fromShip = normalizeShip(account.ship);
|
||||
const story = buildMediaStory(text, uploadedUrl);
|
||||
|
||||
|
|
@ -255,22 +257,15 @@ const tlonOutbound: ChannelOutboundAdapter = {
|
|||
story,
|
||||
});
|
||||
}
|
||||
const replyId = (replyToId ?? threadId) ? String(replyToId ?? threadId) : undefined;
|
||||
return await sendGroupMessageWithStory({
|
||||
api,
|
||||
fromShip,
|
||||
hostShip: parsed.hostShip,
|
||||
channelName: parsed.channelName,
|
||||
story,
|
||||
replyToId: replyId,
|
||||
replyToId: resolveReplyId(replyToId, threadId),
|
||||
});
|
||||
} finally {
|
||||
try {
|
||||
await api.delete();
|
||||
} catch {
|
||||
// ignore cleanup errors
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue