feat: add providers CLI and multi-account onboarding

This commit is contained in:
Peter Steinberger
2026-01-08 01:18:37 +01:00
parent 6b3ed40d0f
commit 05b8679c8b
54 changed files with 4399 additions and 1448 deletions

View File

@@ -85,6 +85,20 @@ describe("resolveTextChunkLimit", () => {
expect(resolveTextChunkLimit(cfg, "telegram")).toBe(1234);
});
it("prefers account overrides when provided", () => {
const cfg = {
telegram: {
textChunkLimit: 2000,
accounts: {
default: { textChunkLimit: 1234 },
primary: { textChunkLimit: 777 },
},
},
};
expect(resolveTextChunkLimit(cfg, "telegram", "primary")).toBe(777);
expect(resolveTextChunkLimit(cfg, "telegram", "default")).toBe(1234);
});
it("uses the matching provider override", () => {
const cfg = {
discord: { textChunkLimit: 111 },

View File

@@ -8,6 +8,7 @@ import {
isSafeFenceBreak,
parseFenceSpans,
} from "../markdown/fences.js";
import { normalizeAccountId } from "../routing/session-key.js";
export type TextChunkProvider =
| "whatsapp"
@@ -31,15 +32,44 @@ const DEFAULT_CHUNK_LIMIT_BY_PROVIDER: Record<TextChunkProvider, number> = {
export function resolveTextChunkLimit(
cfg: ClawdbotConfig | undefined,
provider?: TextChunkProvider,
accountId?: string | null,
): number {
const providerOverride = (() => {
if (!provider) return undefined;
if (provider === "whatsapp") return cfg?.whatsapp?.textChunkLimit;
if (provider === "telegram") return cfg?.telegram?.textChunkLimit;
if (provider === "discord") return cfg?.discord?.textChunkLimit;
if (provider === "slack") return cfg?.slack?.textChunkLimit;
if (provider === "signal") return cfg?.signal?.textChunkLimit;
if (provider === "imessage") return cfg?.imessage?.textChunkLimit;
const normalizedAccountId = normalizeAccountId(accountId);
if (provider === "whatsapp") {
return cfg?.whatsapp?.textChunkLimit;
}
if (provider === "telegram") {
return (
cfg?.telegram?.accounts?.[normalizedAccountId]?.textChunkLimit ??
cfg?.telegram?.textChunkLimit
);
}
if (provider === "discord") {
return (
cfg?.discord?.accounts?.[normalizedAccountId]?.textChunkLimit ??
cfg?.discord?.textChunkLimit
);
}
if (provider === "slack") {
return (
cfg?.slack?.accounts?.[normalizedAccountId]?.textChunkLimit ??
cfg?.slack?.textChunkLimit
);
}
if (provider === "signal") {
return (
cfg?.signal?.accounts?.[normalizedAccountId]?.textChunkLimit ??
cfg?.signal?.textChunkLimit
);
}
if (provider === "imessage") {
return (
cfg?.imessage?.accounts?.[normalizedAccountId]?.textChunkLimit ??
cfg?.imessage?.textChunkLimit
);
}
return undefined;
})();
if (typeof providerOverride === "number" && providerOverride > 0) {

View File

@@ -85,6 +85,7 @@ export async function routeReply(
mediaUrl,
messageThreadId: threadId,
replyToMessageId: resolvedReplyToMessageId,
accountId,
});
return { ok: true, messageId: result.messageId };
}
@@ -93,6 +94,7 @@ export async function routeReply(
const result = await sendMessageSlack(to, text, {
mediaUrl,
threadTs: replyToId,
accountId,
});
return { ok: true, messageId: result.messageId };
}
@@ -101,17 +103,24 @@ export async function routeReply(
const result = await sendMessageDiscord(to, text, {
mediaUrl,
replyTo: replyToId,
accountId,
});
return { ok: true, messageId: result.messageId };
}
case "signal": {
const result = await sendMessageSignal(to, text, { mediaUrl });
const result = await sendMessageSignal(to, text, {
mediaUrl,
accountId,
});
return { ok: true, messageId: result.messageId };
}
case "imessage": {
const result = await sendMessageIMessage(to, text, { mediaUrl });
const result = await sendMessageIMessage(to, text, {
mediaUrl,
accountId,
});
return { ok: true, messageId: result.messageId };
}