style: apply biome formatting

This commit is contained in:
Peter Steinberger
2026-01-02 01:29:05 +01:00
parent 336048441c
commit c31070db24
13 changed files with 78 additions and 62 deletions

View File

@@ -438,11 +438,11 @@ export async function agentCommand(
? whatsappTarget
: deliveryProvider === "discord"
? discordTarget
: deliveryProvider === "signal"
? signalTarget
: deliveryProvider === "imessage"
? imessageTarget
: undefined;
: deliveryProvider === "signal"
? signalTarget
: deliveryProvider === "imessage"
? imessageTarget
: undefined;
const message = `Delivery failed (${deliveryProvider}${deliveryTarget ? ` to ${deliveryTarget}` : ""}): ${String(err)}`;
runtime.error?.(message);
if (!runtime.error) runtime.log(message);

View File

@@ -102,7 +102,13 @@ export type HookMappingConfig = {
messageTemplate?: string;
textTemplate?: string;
deliver?: boolean;
channel?: "last" | "whatsapp" | "telegram" | "discord" | "signal" | "imessage";
channel?:
| "last"
| "whatsapp"
| "telegram"
| "discord"
| "signal"
| "imessage";
to?: string;
thinking?: string;
timeoutSeconds?: number;
@@ -940,11 +946,7 @@ const ClawdisSchema = z.object({
cliPath: z.string().optional(),
dbPath: z.string().optional(),
service: z
.union([
z.literal("imessage"),
z.literal("sms"),
z.literal("auto"),
])
.union([z.literal("imessage"), z.literal("sms"), z.literal("auto")])
.optional(),
region: z.string().optional(),
allowFrom: z.array(z.union([z.string(), z.number()])).optional(),

View File

@@ -53,7 +53,9 @@ function normalizeReactionEmoji(raw: string) {
throw new Error("emoji required");
}
const customMatch = trimmed.match(/^<a?:([^:>]+):(\d+)>$/);
const identifier = customMatch ? `${customMatch[1]}:${customMatch[2]}` : trimmed;
const identifier = customMatch
? `${customMatch[1]}:${customMatch[2]}`
: trimmed;
return encodeURIComponent(identifier);
}

View File

@@ -3664,7 +3664,9 @@ describe("gateway server", () => {
ws,
(o) => {
if (o.type !== "event" || o.event !== "chat") return false;
const payload = o.payload as { state?: unknown; runId?: unknown } | undefined;
const payload = o.payload as
| { state?: unknown; runId?: unknown }
| undefined;
return payload?.state === "final" && payload.runId === "run-auto-1";
},
8000,

View File

@@ -74,12 +74,12 @@ import {
sendMessageDiscord,
} from "../discord/index.js";
import { type DiscordProbe, probeDiscord } from "../discord/probe.js";
import { isVerbose } from "../globals.js";
import {
monitorIMessageProvider,
sendMessageIMessage,
} from "../imessage/index.js";
import { probeIMessage, type IMessageProbe } from "../imessage/probe.js";
import { isVerbose } from "../globals.js";
import { type IMessageProbe, probeIMessage } from "../imessage/probe.js";
import {
clearAgentRunContext,
getAgentRunContext,
@@ -1394,14 +1394,13 @@ export async function startGatewayServer(
? channelRaw
: channelRaw === "imsg"
? "imessage"
: channelRaw === undefined
? "last"
: null;
: channelRaw === undefined
? "last"
: null;
if (channel === null) {
return {
ok: false,
error:
"channel must be last|whatsapp|telegram|discord|signal|imessage",
error: "channel must be last|whatsapp|telegram|discord|signal|imessage",
};
}
const toRaw = payload.to;
@@ -4331,7 +4330,8 @@ export async function startGatewayServer(
const imessageCfg = cfg.imessage;
const imessageEnabled = imessageCfg?.enabled !== false;
const imessageConfigured = Boolean(imessageCfg) && imessageEnabled;
const imessageConfigured =
Boolean(imessageCfg) && imessageEnabled;
let imessageProbe: IMessageProbe | undefined;
let imessageLastProbeAt: number | null = null;
if (probe && imessageConfigured) {
@@ -6788,9 +6788,7 @@ export async function startGatewayServer(
await Promise.allSettled(
[whatsappTask, telegramTask, signalTask, imessageTask].filter(
Boolean,
) as Array<
Promise<unknown>
>,
) as Array<Promise<unknown>>,
);
await new Promise<void>((resolve) => wss.close(() => resolve()));
await new Promise<void>((resolve, reject) =>

View File

@@ -1,4 +1,4 @@
import { spawn, type ChildProcessWithoutNullStreams } from "node:child_process";
import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process";
import { createInterface, type Interface } from "node:readline";
import type { RuntimeEnv } from "../runtime.js";
@@ -51,7 +51,9 @@ export class IMessageRpcClient {
constructor(opts: IMessageRpcClientOptions = {}) {
this.cliPath = opts.cliPath?.trim() || "imsg";
this.dbPath = opts.dbPath?.trim() ? resolveUserPath(opts.dbPath) : undefined;
this.dbPath = opts.dbPath?.trim()
? resolveUserPath(opts.dbPath)
: undefined;
this.runtime = opts.runtime;
this.onNotification = opts.onNotification;
this.closed = new Promise((resolve) => {
@@ -166,7 +168,7 @@ export class IMessageRpcClient {
let parsed: IMessageRpcResponse<unknown>;
try {
parsed = JSON.parse(line) as IMessageRpcResponse<unknown>;
} catch (err) {
} catch (_err) {
this.runtime?.error?.(`imsg rpc: failed to parse ${line}`);
return;
}

View File

@@ -9,7 +9,9 @@ const replyMock = vi.fn();
const updateLastRouteMock = vi.fn();
let config: Record<string, unknown> = {};
let notificationHandler: ((msg: { method: string; params?: unknown }) => void) | undefined;
let notificationHandler:
| ((msg: { method: string; params?: unknown }) => void)
| undefined;
let closeResolve: (() => void) | undefined;
vi.mock("../config/config.js", () => ({
@@ -30,24 +32,27 @@ vi.mock("../config/sessions.js", () => ({
}));
vi.mock("./client.js", () => ({
createIMessageRpcClient: vi.fn(async (opts: { onNotification?: typeof notificationHandler }) => {
notificationHandler = opts.onNotification;
return {
request: (...args: unknown[]) => requestMock(...args),
waitForClose: () =>
new Promise<void>((resolve) => {
closeResolve = resolve;
}),
stop: (...args: unknown[]) => stopMock(...args),
};
}),
createIMessageRpcClient: vi.fn(
async (opts: { onNotification?: typeof notificationHandler }) => {
notificationHandler = opts.onNotification;
return {
request: (...args: unknown[]) => requestMock(...args),
waitForClose: () =>
new Promise<void>((resolve) => {
closeResolve = resolve;
}),
stop: (...args: unknown[]) => stopMock(...args),
};
},
),
}));
const flush = () => new Promise((resolve) => setTimeout(resolve, 0));
async function waitForSubscribe() {
for (let i = 0; i < 5; i += 1) {
if (requestMock.mock.calls.some((call) => call[0] === "watch.subscribe")) return;
if (requestMock.mock.calls.some((call) => call[0] === "watch.subscribe"))
return;
await flush();
}
}
@@ -62,7 +67,8 @@ beforeEach(() => {
},
};
requestMock.mockReset().mockImplementation((method: string) => {
if (method === "watch.subscribe") return Promise.resolve({ subscription: 1 });
if (method === "watch.subscribe")
return Promise.resolve({ subscription: 1 });
return Promise.resolve({});
});
stopMock.mockReset().mockResolvedValue(undefined);

View File

@@ -176,15 +176,18 @@ export async function monitorIMessageProvider(
return;
}
const attachments = includeAttachments ? message.attachments ?? [] : [];
const attachments = includeAttachments ? (message.attachments ?? []) : [];
const firstAttachment = attachments?.find(
(entry) => entry?.original_path && !entry?.missing,
);
const mediaPath = firstAttachment?.original_path ?? undefined;
const mediaType = firstAttachment?.mime_type ?? undefined;
const kind = mediaKindFromMime(mediaType ?? undefined);
const placeholder =
kind ? `<media:${kind}>` : attachments?.length ? "<media:attachment>" : "";
const placeholder = kind
? `<media:${kind}>`
: attachments?.length
? "<media:attachment>"
: "";
const bodyText = messageText || placeholder;
if (!bodyText) return;
@@ -279,7 +282,9 @@ export async function monitorIMessageProvider(
const abort = opts.abortSignal;
const onAbort = () => {
if (subscriptionId) {
void client.request("watch.unsubscribe", { subscription: subscriptionId });
void client.request("watch.unsubscribe", {
subscription: subscriptionId,
});
}
void client.stop();
};

View File

@@ -7,9 +7,7 @@ export type IMessageProbe = {
error?: string | null;
};
export async function probeIMessage(
timeoutMs = 2000,
): Promise<IMessageProbe> {
export async function probeIMessage(timeoutMs = 2000): Promise<IMessageProbe> {
const cfg = loadConfig();
const cliPath = cfg.imessage?.cliPath?.trim() || "imsg";
const dbPath = cfg.imessage?.dbPath?.trim();

View File

@@ -5,8 +5,8 @@ import { loadWebMedia } from "../web/media.js";
import { createIMessageRpcClient, type IMessageRpcClient } from "./client.js";
import {
formatIMessageChatTarget,
parseIMessageTarget,
type IMessageService,
parseIMessageTarget,
} from "./targets.js";
export type IMessageSendOpts = {
@@ -38,9 +38,7 @@ function resolveDbPath(explicit?: string): string | undefined {
function resolveService(explicit?: IMessageService): IMessageService {
const cfg = loadConfig();
return (
explicit ||
(cfg.imessage?.service as IMessageService | undefined) ||
"auto"
explicit || (cfg.imessage?.service as IMessageService | undefined) || "auto"
);
}
@@ -85,7 +83,8 @@ export async function sendMessageIMessage(
filePath = resolved.path;
if (!message.trim()) {
const kind = mediaKindFromMime(resolved.contentType ?? undefined);
if (kind) message = kind === "image" ? "<media:image>" : `<media:${kind}>`;
if (kind)
message = kind === "image" ? "<media:image>" : `<media:${kind}>`;
}
}
@@ -110,7 +109,8 @@ export async function sendMessageIMessage(
params.to = target.to;
}
const client = opts.client ?? (await createIMessageRpcClient({ cliPath, dbPath }));
const client =
opts.client ?? (await createIMessageRpcClient({ cliPath, dbPath }));
const shouldClose = !opts.client;
try {
const result = await client.request<{ ok?: boolean }>("send", params, {

View File

@@ -27,9 +27,7 @@ describe("imessage targets", () => {
expect(normalizeIMessageHandle("Name@Example.com")).toBe(
"name@example.com",
);
expect(normalizeIMessageHandle(" +1 (555) 222-3333 ")).toBe(
"+15552223333",
);
expect(normalizeIMessageHandle(" +1 (555) 222-3333 ")).toBe("+15552223333");
});
it("checks allowFrom against chat_id", () => {

View File

@@ -35,9 +35,12 @@ export function normalizeIMessageHandle(raw: string): string {
const trimmed = raw.trim();
if (!trimmed) return "";
const lowered = trimmed.toLowerCase();
if (lowered.startsWith("imessage:")) return normalizeIMessageHandle(trimmed.slice(9));
if (lowered.startsWith("sms:")) return normalizeIMessageHandle(trimmed.slice(4));
if (lowered.startsWith("auto:")) return normalizeIMessageHandle(trimmed.slice(5));
if (lowered.startsWith("imessage:"))
return normalizeIMessageHandle(trimmed.slice(9));
if (lowered.startsWith("sms:"))
return normalizeIMessageHandle(trimmed.slice(4));
if (lowered.startsWith("auto:"))
return normalizeIMessageHandle(trimmed.slice(5));
if (trimmed.includes("@")) return trimmed.toLowerCase();
const normalized = normalizeE164(trimmed);
if (normalized) return normalized;

View File

@@ -1,10 +1,10 @@
import { describe, expect, test } from "vitest";
import {
clearAgentRunContext,
emitAgentEvent,
getAgentRunContext,
onAgentEvent,
registerAgentRunContext,
getAgentRunContext,
clearAgentRunContext,
resetAgentRunContextForTest,
} from "./agent-events.js";