style: oxfmt format

This commit is contained in:
Peter Steinberger
2026-01-17 05:48:34 +00:00
parent 8b42902cee
commit e59d8c5436
47 changed files with 152 additions and 165 deletions

View File

@@ -97,7 +97,8 @@ const execSchema = Type.Object({
),
pty: Type.Optional(
Type.Boolean({
description: "Run in a pseudo-terminal (PTY) when available (TTY-required CLIs, coding agents)",
description:
"Run in a pseudo-terminal (PTY) when available (TTY-required CLIs, coding agents)",
}),
),
elevated: Type.Optional(

View File

@@ -68,9 +68,7 @@ export function buildEmbeddedRunPayloads(params: {
if (errorText) replyItems.push({ text: errorText, isError: true });
const inlineToolResults =
params.inlineToolResultsAllowed &&
params.verboseLevel !== "off" &&
params.toolMetas.length > 0;
params.inlineToolResultsAllowed && params.verboseLevel !== "off" && params.toolMetas.length > 0;
if (inlineToolResults) {
for (const { toolName, meta } of params.toolMetas) {
const agg = formatToolAggregate(toolName, meta ? [meta] : []);

View File

@@ -9,9 +9,7 @@ import {
resolveStorePath,
} from "../config/sessions.js";
import { normalizeMainKey } from "../routing/session-key.js";
import {
resolveQueueSettings,
} from "../auto-reply/reply/queue.js";
import { resolveQueueSettings } from "../auto-reply/reply/queue.js";
import { callGateway } from "../gateway/call.js";
import { defaultRuntime } from "../runtime.js";
import {

View File

@@ -54,9 +54,7 @@ export function loadSubagentRegistryFromDisk(): Map<string, SubagentRunRecord> {
? typed.announceCompletedAt
: undefined;
const cleanupCompletedAt =
typeof typed.cleanupCompletedAt === "number"
? typed.cleanupCompletedAt
: legacyCompletedAt;
typeof typed.cleanupCompletedAt === "number" ? typed.cleanupCompletedAt : legacyCompletedAt;
const cleanupHandled =
typeof typed.cleanupHandled === "boolean"
? typed.cleanupHandled

View File

@@ -1,10 +1,7 @@
import { loadConfig } from "../config/config.js";
import { callGateway } from "../gateway/call.js";
import { onAgentEvent } from "../infra/agent-events.js";
import {
type DeliveryContext,
normalizeDeliveryContext,
} from "../utils/delivery-context.js";
import { type DeliveryContext, normalizeDeliveryContext } from "../utils/delivery-context.js";
import { runSubagentAnnounceFlow, type SubagentRunOutcome } from "./subagent-announce.js";
import {
loadSubagentRegistryFromDisk,

View File

@@ -26,9 +26,7 @@ const AllMessageActions = CHANNEL_MESSAGE_ACTION_NAMES;
function buildRoutingSchema() {
return {
channel: Type.Optional(Type.String()),
target: Type.Optional(
channelTargetSchema({ description: "Target channel/user id or name." }),
),
target: Type.Optional(channelTargetSchema({ description: "Target channel/user id or name." })),
targets: Type.Optional(channelTargetsSchema()),
accountId: Type.Optional(Type.String()),
dryRun: Type.Optional(Type.Boolean()),
@@ -188,7 +186,6 @@ function buildMessageToolSchemaProps(options: { includeButtons: boolean }) {
};
}
function buildMessageToolSchemaFromActions(
actions: readonly string[],
options: { includeButtons: boolean },

View File

@@ -44,8 +44,6 @@ describe("formatInboundBodyWithSenderMeta", () => {
it("does not append when the body already includes a sender prefix", () => {
const ctx: MsgContext = { ChatType: "group", SenderName: "Alice", SenderId: "A1" };
expect(formatInboundBodyWithSenderMeta({ ctx, body: "Alice (A1): hi" })).toBe(
"Alice (A1): hi",
);
expect(formatInboundBodyWithSenderMeta({ ctx, body: "Alice (A1): hi" })).toBe("Alice (A1): hi");
});
});

View File

@@ -16,4 +16,3 @@ describe("normalizeInboundTextNewlines", () => {
expect(normalizeInboundTextNewlines("a\\nb")).toBe("a\nb");
});
});

View File

@@ -129,7 +129,8 @@ export async function initSessionState(params: {
const groupResolution = resolveGroupSessionKey(sessionCtxForState) ?? undefined;
const normalizedChatType = normalizeChatType(ctx.ChatType);
const isGroup = normalizedChatType != null && normalizedChatType !== "direct" ? true : Boolean(groupResolution);
const isGroup =
normalizedChatType != null && normalizedChatType !== "direct" ? true : Boolean(groupResolution);
// Prefer CommandBody/RawBody (clean message) for command detection; fall back
// to Body which may contain structural context (history, sender labels).
const commandSource = ctx.BodyForCommands ?? ctx.CommandBody ?? ctx.RawBody ?? ctx.Body ?? "";

View File

@@ -20,13 +20,20 @@ describe("resolveConversationLabel", () => {
});
it("does not append ids for #rooms/channels", () => {
const ctx: MsgContext = { ChatType: "channel", GroupSubject: "#general", From: "slack:channel:C123" };
const ctx: MsgContext = {
ChatType: "channel",
GroupSubject: "#general",
From: "slack:channel:C123",
};
expect(resolveConversationLabel(ctx)).toBe("#general");
});
it("appends ids for WhatsApp-like group ids when a subject exists", () => {
const ctx: MsgContext = { ChatType: "group", GroupSubject: "Family", From: "whatsapp:group:123@g.us" };
const ctx: MsgContext = {
ChatType: "group",
GroupSubject: "Family",
From: "whatsapp:group:123@g.us",
};
expect(resolveConversationLabel(ctx)).toBe("Family id:123@g.us");
});
});

View File

@@ -43,4 +43,3 @@ export function resolveConversationLabel(ctx: MsgContext): string | undefined {
if (base.startsWith("#") || base.startsWith("@")) return base;
return `${base} id:${id}`;
}

View File

@@ -53,10 +53,7 @@ export const whatsappOutbound: ChannelOutboundAdapter = {
}
return {
ok: false,
error: missingTargetError(
"WhatsApp",
"<E.164|group JID> or channels.whatsapp.allowFrom[0]",
),
error: missingTargetError("WhatsApp", "<E.164|group JID> or channels.whatsapp.allowFrom[0]"),
};
},
sendText: async ({ to, text, accountId, deps, gifPlayback }) => {

View File

@@ -202,10 +202,7 @@ export const signalPlugin: ChannelPlugin<ResolvedSignalAccount> = {
if (!trimmed) {
return {
ok: false,
error: missingTargetError(
"Signal",
"<E.164|group:ID|signal:group:ID|signal:+E.164>",
),
error: missingTargetError("Signal", "<E.164|group:ID|signal:group:ID|signal:+E.164>"),
};
}
return { ok: true, to: trimmed };

View File

@@ -342,7 +342,10 @@ export const whatsappPlugin: ChannelPlugin<ResolvedWhatsAppAccount> = {
}
return {
ok: false,
error: missingTargetError("WhatsApp", "<E.164|group JID> or channels.whatsapp.allowFrom[0]"),
error: missingTargetError(
"WhatsApp",
"<E.164|group JID> or channels.whatsapp.allowFrom[0]",
),
};
},
sendText: async ({ to, text, accountId, deps, gifPlayback }) => {

View File

@@ -11,7 +11,9 @@ describe("validateSenderIdentity", () => {
it("requires some sender identity for non-direct chats", () => {
const ctx: MsgContext = { ChatType: "group" };
expect(validateSenderIdentity(ctx)).toContain("missing sender identity (SenderId/SenderName/SenderUsername/SenderE164)");
expect(validateSenderIdentity(ctx)).toContain(
"missing sender identity (SenderId/SenderName/SenderUsername/SenderE164)",
);
});
it("validates SenderE164 and SenderUsername shape", () => {
@@ -27,4 +29,3 @@ describe("validateSenderIdentity", () => {
]);
});
});

View File

@@ -25,8 +25,10 @@ export function validateSenderIdentity(ctx: MsgContext): string[] {
}
if (senderUsername) {
if (senderUsername.includes("@")) issues.push(`SenderUsername should not include "@": ${senderUsername}`);
if (/\s/.test(senderUsername)) issues.push(`SenderUsername should not include whitespace: ${senderUsername}`);
if (senderUsername.includes("@"))
issues.push(`SenderUsername should not include "@": ${senderUsername}`);
if (/\s/.test(senderUsername))
issues.push(`SenderUsername should not include whitespace: ${senderUsername}`);
}
if (ctx.SenderId != null && !senderId) {
@@ -35,4 +37,3 @@ export function validateSenderIdentity(ctx: MsgContext): string[] {
return issues;
}

View File

@@ -20,4 +20,3 @@ export function createOutboundSendDeps(deps: CliDeps): OutboundSendDeps {
sendIMessage: deps.sendMessageIMessage,
};
}

View File

@@ -40,9 +40,7 @@ export function registerMessageDiscordAdminCommands(message: Command, helpers: M
const channel = message.command("channel").description("Channel actions");
helpers
.withMessageBase(
helpers.withRequiredMessageTarget(
channel.command("info").description("Fetch channel info"),
),
helpers.withRequiredMessageTarget(channel.command("info").description("Fetch channel info")),
)
.action(async (opts) => {
await helpers.runMessageAction("channel-info", opts);

View File

@@ -21,7 +21,9 @@ export function registerMessagePinCommands(message: Command, helpers: MessageCli
}),
helpers
.withMessageBase(
helpers.withRequiredMessageTarget(message.command("pins").description("List pinned messages")),
helpers.withRequiredMessageTarget(
message.command("pins").description("List pinned messages"),
),
)
.option("--limit <n>", "Result limit")
.action(async (opts) => {

View File

@@ -7,7 +7,9 @@ export function registerMessageReadEditDeleteCommands(
) {
helpers
.withMessageBase(
helpers.withRequiredMessageTarget(message.command("read").description("Read recent messages")),
helpers.withRequiredMessageTarget(
message.command("read").description("Read recent messages"),
),
)
.option("--limit <n>", "Result limit")
.option("--before <id>", "Read/search before id")

View File

@@ -34,9 +34,7 @@ function resolveDeliveryAccountId(params: {
const sessionOrigin = deliveryContextFromSession(params.sessionEntry);
return (
normalizeAccountId(params.opts.accountId) ??
(params.targetMode === "implicit"
? normalizeAccountId(sessionOrigin?.accountId)
: undefined)
(params.targetMode === "implicit" ? normalizeAccountId(sessionOrigin?.accountId) : undefined)
);
}

View File

@@ -332,9 +332,7 @@ export const LEGACY_CONFIG_MIGRATIONS_PART_2: LegacyConfigMigration[] = [
const tools = ensureRecord(raw, "tools");
const media = ensureRecord(tools, "media");
const mediaAudio = ensureRecord(media, "audio");
const models = Array.isArray(mediaAudio.models)
? (mediaAudio.models as unknown[])
: [];
const models = Array.isArray(mediaAudio.models) ? (mediaAudio.models as unknown[]) : [];
if (models.length === 0) {
mediaAudio.enabled = true;
mediaAudio.models = [mapped];
@@ -355,9 +353,7 @@ export const LEGACY_CONFIG_MIGRATIONS_PART_2: LegacyConfigMigration[] = [
const tools = ensureRecord(raw, "tools");
const media = ensureRecord(tools, "media");
const mediaAudio = ensureRecord(media, "audio");
const models = Array.isArray(mediaAudio.models)
? (mediaAudio.models as unknown[])
: [];
const models = Array.isArray(mediaAudio.models) ? (mediaAudio.models as unknown[]) : [];
if (models.length === 0) {
mediaAudio.enabled = true;
mediaAudio.models = [mapped];

View File

@@ -274,7 +274,9 @@ export const MediaUnderstandingAttachmentsSchema = z
.object({
mode: z.union([z.literal("first"), z.literal("all")]).optional(),
maxAttachments: z.number().int().positive().optional(),
prefer: z.union([z.literal("first"), z.literal("last"), z.literal("path"), z.literal("url")]).optional(),
prefer: z
.union([z.literal("first"), z.literal("last"), z.literal("path"), z.literal("url")])
.optional(),
})
.optional();

View File

@@ -8,7 +8,10 @@ import {
} from "../../config/sessions.js";
import { resolveMessageChannelSelection } from "../../infra/outbound/channel-selection.js";
import type { OutboundChannel } from "../../infra/outbound/targets.js";
import { resolveOutboundTarget, resolveSessionDeliveryTarget } from "../../infra/outbound/targets.js";
import {
resolveOutboundTarget,
resolveSessionDeliveryTarget,
} from "../../infra/outbound/targets.js";
export async function resolveDeliveryTarget(
cfg: ClawdbotConfig,

View File

@@ -87,4 +87,3 @@ describe("discord processDiscordMessage inbound contract", () => {
expectInboundContextContract(capturedCtx!);
});
});

View File

@@ -8,10 +8,7 @@ import {
extractShortModelName,
type ResponsePrefixContext,
} from "../../auto-reply/reply/response-prefix-template.js";
import {
formatInboundEnvelope,
formatThreadStarterEnvelope,
} from "../../auto-reply/envelope.js";
import { formatInboundEnvelope, formatThreadStarterEnvelope } from "../../auto-reply/envelope.js";
import { dispatchReplyFromConfig } from "../../auto-reply/reply/dispatch-from-config.js";
import {
buildPendingHistoryContextFromMap,
@@ -126,7 +123,7 @@ export async function processDiscordMessage(ctx: DiscordMessagePreflightContext)
const senderLabel =
senderDisplay && senderTag && senderDisplay !== senderTag
? `${senderDisplay} (${senderTag})`
: senderDisplay ?? senderTag ?? author.id;
: (senderDisplay ?? senderTag ?? author.id);
const groupRoom = isGuildMessage && displayChannelSlug ? `#${displayChannelSlug}` : undefined;
const groupSubject = isDirectMessage ? undefined : groupRoom;
const channelDescription = channelInfo?.topic?.trim();

View File

@@ -13,7 +13,10 @@ import type {
} from "../../channels/plugins/types.js";
import type { ClawdbotConfig } from "../../config/config.js";
import type { GatewayClientMode, GatewayClientName } from "../../utils/message-channel.js";
import { listConfiguredMessageChannels, resolveMessageChannelSelection } from "./channel-selection.js";
import {
listConfiguredMessageChannels,
resolveMessageChannelSelection,
} from "./channel-selection.js";
import { applyTargetToParams } from "./channel-target.js";
import type { OutboundSendDeps } from "./deliver.js";
import type { MessagePollResult, MessageSendResult } from "./message.js";
@@ -483,10 +486,7 @@ async function handlePollAction(ctx: ResolvedActionContext): Promise<MessageActi
async function handlePluginAction(ctx: ResolvedActionContext): Promise<MessageActionRunResult> {
const { cfg, params, channel, accountId, dryRun, gateway, input } = ctx;
const action = input.action as Exclude<
ChannelMessageActionName,
"send" | "poll" | "broadcast"
>;
const action = input.action as Exclude<ChannelMessageActionName, "send" | "poll" | "broadcast">;
if (dryRun) {
return {
kind: "action",

View File

@@ -1,9 +1,6 @@
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import { dispatchChannelMessageAction } from "../../channels/plugins/message-actions.js";
import type {
ChannelId,
ChannelThreadingToolContext,
} from "../../channels/plugins/types.js";
import type { ChannelId, ChannelThreadingToolContext } from "../../channels/plugins/types.js";
import type { ClawdbotConfig } from "../../config/config.js";
import type { GatewayClientMode, GatewayClientName } from "../../utils/message-channel.js";
import type { OutboundSendDeps } from "./deliver.js";

View File

@@ -340,9 +340,7 @@ describe("applyMediaUnderstanding", () => {
expect(result.appliedAudio).toBe(true);
expect(ctx.Transcript).toBe("Audio 1:\nnote-a.ogg\n\nAudio 2:\nnote-b.ogg");
expect(ctx.Body).toBe(
["[Audio 1/2]\nTranscript:\nnote-a.ogg", "[Audio 2/2]\nTranscript:\nnote-b.ogg"].join(
"\n\n",
),
["[Audio 1/2]\nTranscript:\nnote-a.ogg", "[Audio 2/2]\nTranscript:\nnote-b.ogg"].join("\n\n"),
);
});
});

View File

@@ -9,11 +9,7 @@ import type {
MediaUnderstandingConfig,
MediaUnderstandingModelConfig,
} from "../config/types.tools.js";
import {
MediaAttachmentCache,
normalizeAttachments,
selectAttachments,
} from "./attachments.js";
import { MediaAttachmentCache, normalizeAttachments, selectAttachments } from "./attachments.js";
import {
CLI_OUTPUT_MAX_BUFFER,
DEFAULT_AUDIO_MODELS,
@@ -85,7 +81,9 @@ async function runProviderEntry(params: {
const maxBytes = resolveMaxBytes({ capability, entry, cfg, config: params.config });
const maxChars = resolveMaxChars({ capability, entry, cfg, config: params.config });
const timeoutMs = resolveTimeoutMs(
entry.timeoutSeconds ?? params.config?.timeoutSeconds ?? cfg.tools?.media?.[capability]?.timeoutSeconds,
entry.timeoutSeconds ??
params.config?.timeoutSeconds ??
cfg.tools?.media?.[capability]?.timeoutSeconds,
DEFAULT_TIMEOUT_SECONDS[capability],
);
const prompt = resolvePrompt(
@@ -250,7 +248,9 @@ async function runCliEntry(params: {
const maxBytes = resolveMaxBytes({ capability, entry, cfg, config: params.config });
const maxChars = resolveMaxChars({ capability, entry, cfg, config: params.config });
const timeoutMs = resolveTimeoutMs(
entry.timeoutSeconds ?? params.config?.timeoutSeconds ?? cfg.tools?.media?.[capability]?.timeoutSeconds,
entry.timeoutSeconds ??
params.config?.timeoutSeconds ??
cfg.tools?.media?.[capability]?.timeoutSeconds,
DEFAULT_TIMEOUT_SECONDS[capability],
);
const prompt = resolvePrompt(

View File

@@ -317,10 +317,7 @@ export class MediaAttachmentCache {
timeoutMs: params.timeoutMs,
});
const extension = path.extname(bufferResult.fileName || "") || "";
const tmpPath = path.join(
os.tmpdir(),
`clawdbot-media-${crypto.randomUUID()}${extension}`,
);
const tmpPath = path.join(os.tmpdir(), `clawdbot-media-${crypto.randomUUID()}${extension}`);
await fs.writeFile(tmpPath, bufferResult.buffer);
entry.tempPath = tmpPath;
entry.tempCleanup = async () => {
@@ -348,8 +345,9 @@ export class MediaAttachmentCache {
}
return existing;
}
const attachment =
this.attachments.find((item) => item.index === attachmentIndex) ?? { index: attachmentIndex };
const attachment = this.attachments.find((item) => item.index === attachmentIndex) ?? {
index: attachmentIndex,
};
const entry: AttachmentCacheEntry = {
attachment,
resolvedPath: this.resolveLocalPath(attachment),

View File

@@ -10,8 +10,6 @@ export class MediaUnderstandingSkipError extends Error {
}
}
export function isMediaUnderstandingSkipError(
err: unknown,
): err is MediaUnderstandingSkipError {
export function isMediaUnderstandingSkipError(err: unknown): err is MediaUnderstandingSkipError {
return err instanceof MediaUnderstandingSkipError;
}

View File

@@ -88,7 +88,5 @@ export function formatMediaUnderstandingBody(params: {
export function formatAudioTranscripts(outputs: MediaUnderstandingOutput[]): string {
if (outputs.length === 1) return outputs[0].text;
return outputs
.map((output, index) => `Audio ${index + 1}:\n${output.text}`)
.join("\n\n");
return outputs.map((output, index) => `Audio ${index + 1}:\n${output.text}`).join("\n\n");
}

View File

@@ -383,13 +383,19 @@ export async function collectPluginsTrustFindings(params: {
if (!allowConfigured) {
const hasString = (value: unknown) => typeof value === "string" && value.trim().length > 0;
const hasAccountStringKey = (account: unknown, key: string) =>
Boolean(account && typeof account === "object" && hasString((account as Record<string, unknown>)[key]));
Boolean(
account &&
typeof account === "object" &&
hasString((account as Record<string, unknown>)[key]),
);
const discordConfigured =
hasString(params.cfg.channels?.discord?.token) ||
Boolean(
params.cfg.channels?.discord?.accounts &&
Object.values(params.cfg.channels.discord.accounts).some((a) => hasAccountStringKey(a, "token")),
Object.values(params.cfg.channels.discord.accounts).some((a) =>
hasAccountStringKey(a, "token"),
),
) ||
hasString(process.env.DISCORD_BOT_TOKEN);

View File

@@ -505,10 +505,8 @@ async function collectChannelSecurityFindings(params: {
if (!allowTextCommands) continue;
const telegramCfg =
(account as { config?: Record<string, unknown> } | null)?.config ?? ({} as Record<
string,
unknown
>);
(account as { config?: Record<string, unknown> } | null)?.config ??
({} as Record<string, unknown>);
const groupPolicy = (telegramCfg.groupPolicy as string | undefined) ?? "allowlist";
const groups = telegramCfg.groups as Record<string, unknown> | undefined;
const groupsConfigured = Boolean(groups) && Object.keys(groups ?? {}).length > 0;
@@ -518,7 +516,9 @@ async function collectChannelSecurityFindings(params: {
const storeAllowFrom = await readChannelAllowFromStore("telegram").catch(() => []);
const storeHasWildcard = storeAllowFrom.some((v) => String(v).trim() === "*");
const groupAllowFrom = Array.isArray(telegramCfg.groupAllowFrom) ? telegramCfg.groupAllowFrom : [];
const groupAllowFrom = Array.isArray(telegramCfg.groupAllowFrom)
? telegramCfg.groupAllowFrom
: [];
const groupAllowFromHasWildcard = groupAllowFrom.some((v) => String(v).trim() === "*");
const anyGroupOverride = Boolean(
groups &&

View File

@@ -1,6 +1,5 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const dispatchMock = vi.fn();
const readAllowFromMock = vi.fn();
@@ -9,7 +8,6 @@ vi.mock("../pairing/pairing-store.js", () => ({
upsertChannelPairingRequest: vi.fn(),
}));
describe("signal event handler sender prefix", () => {
beforeEach(() => {
dispatchMock.mockReset().mockImplementation(async ({ dispatcher, ctx }) => {

View File

@@ -49,7 +49,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
mediaMaxBytes: 1024,
removeAckAfterReply: false,
});
slackCtx.resolveUserName = async () => ({ name: "Alice" } as any);
slackCtx.resolveUserName = async () => ({ name: "Alice" }) as any;
const account: ResolvedSlackAccount = {
accountId: "default",
@@ -78,4 +78,3 @@ describe("slack prepareSlackMessage inbound contract", () => {
expectInboundContextContract(prepared!.ctxPayload as any);
});
});

View File

@@ -240,7 +240,12 @@ export async function prepareSlackMessage(params: {
: false;
const commandAuthorized = ownerAuthorized || channelCommandAuthorized;
if (allowTextCommands && isRoomish && hasControlCommand(message.text ?? "", cfg) && !commandAuthorized) {
if (
allowTextCommands &&
isRoomish &&
hasControlCommand(message.text ?? "", cfg) &&
!commandAuthorized
) {
logVerbose(`Blocked slack control command from unauthorized sender ${senderId}`);
return null;
}

View File

@@ -251,7 +251,9 @@ export const registerTelegramNativeCommands = ({
const groupSystemPrompt =
systemPromptParts.length > 0 ? systemPromptParts.join("\n\n") : undefined;
const conversationLabel = isGroup
? (msg.chat.title ? `${msg.chat.title} id:${chatId}` : `group:${chatId}`)
? msg.chat.title
? `${msg.chat.title} id:${chatId}`
: `group:${chatId}`
: (buildSenderName(msg) ?? String(senderId || chatId));
const ctxPayload = finalizeInboundContext({
Body: prompt,

View File

@@ -38,13 +38,11 @@ describe("delivery context helpers", () => {
});
it("builds stable keys only when channel and to are present", () => {
expect(deliveryContextKey({ channel: "whatsapp", to: "+1555" })).toBe(
"whatsapp|+1555|",
);
expect(deliveryContextKey({ channel: "whatsapp", to: "+1555" })).toBe("whatsapp|+1555|");
expect(deliveryContextKey({ channel: "whatsapp" })).toBeUndefined();
expect(
deliveryContextKey({ channel: "whatsapp", to: "+1555", accountId: "acct-1" }),
).toBe("whatsapp|+1555|acct-1");
expect(deliveryContextKey({ channel: "whatsapp", to: "+1555", accountId: "acct-1" })).toBe(
"whatsapp|+1555|acct-1",
);
});
it("derives delivery context from a session entry", () => {

View File

@@ -31,7 +31,11 @@ describe("web processMessage inbound contract", () => {
groupSubject: "Test Group",
groupParticipants: [],
} as any,
route: { agentId: "main", accountId: "default", sessionKey: "agent:main:whatsapp:group:123" } as any,
route: {
agentId: "main",
accountId: "default",
sessionKey: "agent:main:whatsapp:group:123",
} as any,
groupHistoryKey: "123@g.us",
groupHistories: new Map(),
groupMemberNames: new Map(),

View File

@@ -18,4 +18,3 @@ export function expectInboundContextContract(ctx: MsgContext) {
expect(label).toBeTruthy();
}
}

View File

@@ -160,4 +160,3 @@ describe("inbound context contract (providers + extensions)", () => {
});
}
});