mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-04 22:20:22 +00:00
refactor: share tlon outbound send context
This commit is contained in:
@@ -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 = {
|
const tlonOutbound: ChannelOutboundAdapter = {
|
||||||
deliveryMode: "direct",
|
deliveryMode: "direct",
|
||||||
textChunkLimit: 10000,
|
textChunkLimit: 10000,
|
||||||
@@ -170,25 +212,8 @@ const tlonOutbound: ChannelOutboundAdapter = {
|
|||||||
return { ok: true, to: parsed.nest };
|
return { ok: true, to: parsed.nest };
|
||||||
},
|
},
|
||||||
sendText: async ({ cfg, to, text, accountId, replyToId, threadId }) => {
|
sendText: async ({ cfg, to, text, accountId, replyToId, threadId }) => {
|
||||||
const account = resolveTlonAccount(cfg, accountId ?? undefined);
|
const { account, parsed } = resolveOutboundContext({ cfg, accountId, to });
|
||||||
if (!account.configured || !account.ship || !account.url || !account.code) {
|
return withHttpPokeAccountApi(account, async (api) => {
|
||||||
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 fromShip = normalizeShip(account.ship);
|
const fromShip = normalizeShip(account.ship);
|
||||||
if (parsed.kind === "dm") {
|
if (parsed.kind === "dm") {
|
||||||
return await sendDm({
|
return await sendDm({
|
||||||
@@ -198,33 +223,18 @@ const tlonOutbound: ChannelOutboundAdapter = {
|
|||||||
text,
|
text,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const replyId = (replyToId ?? threadId) ? String(replyToId ?? threadId) : undefined;
|
|
||||||
return await sendGroupMessage({
|
return await sendGroupMessage({
|
||||||
api,
|
api,
|
||||||
fromShip,
|
fromShip,
|
||||||
hostShip: parsed.hostShip,
|
hostShip: parsed.hostShip,
|
||||||
channelName: parsed.channelName,
|
channelName: parsed.channelName,
|
||||||
text,
|
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 }) => {
|
sendMedia: async ({ cfg, to, text, mediaUrl, accountId, replyToId, threadId }) => {
|
||||||
const account = resolveTlonAccount(cfg, accountId ?? undefined);
|
const { account, parsed } = resolveOutboundContext({ cfg, accountId, to });
|
||||||
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()}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the API client for uploads
|
// Configure the API client for uploads
|
||||||
configureClient({
|
configureClient({
|
||||||
@@ -235,15 +245,7 @@ const tlonOutbound: ChannelOutboundAdapter = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const uploadedUrl = mediaUrl ? await uploadImageFromUrl(mediaUrl) : undefined;
|
const uploadedUrl = mediaUrl ? await uploadImageFromUrl(mediaUrl) : undefined;
|
||||||
|
return withHttpPokeAccountApi(account, async (api) => {
|
||||||
const api = await createHttpPokeApi({
|
|
||||||
url: account.url,
|
|
||||||
ship: account.ship,
|
|
||||||
code: account.code,
|
|
||||||
allowPrivateNetwork: account.allowPrivateNetwork ?? undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const fromShip = normalizeShip(account.ship);
|
const fromShip = normalizeShip(account.ship);
|
||||||
const story = buildMediaStory(text, uploadedUrl);
|
const story = buildMediaStory(text, uploadedUrl);
|
||||||
|
|
||||||
@@ -255,22 +257,15 @@ const tlonOutbound: ChannelOutboundAdapter = {
|
|||||||
story,
|
story,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const replyId = (replyToId ?? threadId) ? String(replyToId ?? threadId) : undefined;
|
|
||||||
return await sendGroupMessageWithStory({
|
return await sendGroupMessageWithStory({
|
||||||
api,
|
api,
|
||||||
fromShip,
|
fromShip,
|
||||||
hostShip: parsed.hostShip,
|
hostShip: parsed.hostShip,
|
||||||
channelName: parsed.channelName,
|
channelName: parsed.channelName,
|
||||||
story,
|
story,
|
||||||
replyToId: replyId,
|
replyToId: resolveReplyId(replyToId, threadId),
|
||||||
});
|
});
|
||||||
} finally {
|
});
|
||||||
try {
|
|
||||||
await api.delete();
|
|
||||||
} catch {
|
|
||||||
// ignore cleanup errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user