style: oxfmt core files

This commit is contained in:
Peter Steinberger
2026-01-19 05:59:29 +00:00
parent d126e7f610
commit 2dc9c95530
9 changed files with 275 additions and 274 deletions

View File

@@ -72,8 +72,7 @@ function collectToolFailures(messages: AgentMessage[]): ToolFailure[] {
isError?: unknown; isError?: unknown;
}; };
if (toolResult.isError !== true) continue; if (toolResult.isError !== true) continue;
const toolCallId = const toolCallId = typeof toolResult.toolCallId === "string" ? toolResult.toolCallId : "";
typeof toolResult.toolCallId === "string" ? toolResult.toolCallId : "";
if (!toolCallId || seen.has(toolCallId)) continue; if (!toolCallId || seen.has(toolCallId)) continue;
seen.add(toolCallId); seen.add(toolCallId);

View File

@@ -15,7 +15,9 @@ function isPrimitive(value: unknown): value is string | number | boolean | bigin
function normalizeForHash(value: unknown): unknown { function normalizeForHash(value: unknown): unknown {
if (value === undefined) return undefined; if (value === undefined) return undefined;
if (Array.isArray(value)) { if (Array.isArray(value)) {
const normalized = value.map(normalizeForHash).filter((item): item is unknown => item !== undefined); const normalized = value
.map(normalizeForHash)
.filter((item): item is unknown => item !== undefined);
const primitives = normalized.filter(isPrimitive); const primitives = normalized.filter(isPrimitive);
if (primitives.length === normalized.length) { if (primitives.length === normalized.length) {
return [...primitives].sort((a, b) => String(a).localeCompare(String(b))); return [...primitives].sort((a, b) => String(a).localeCompare(String(b)));

View File

@@ -256,8 +256,7 @@ export async function ensureSandboxContainer(params: {
registryEntry = registry.entries.find((entry) => entry.containerName === containerName); registryEntry = registry.entries.find((entry) => entry.containerName === containerName);
currentHash = await readContainerConfigHash(containerName); currentHash = await readContainerConfigHash(containerName);
if (!currentHash) { if (!currentHash) {
currentHash = currentHash = registryEntry?.configHash ?? null;
registryEntry?.configHash ?? null;
} }
hashMismatch = !currentHash || currentHash !== expectedHash; hashMismatch = !currentHash || currentHash !== expectedHash;
if (hashMismatch) { if (hashMismatch) {
@@ -296,7 +295,7 @@ export async function ensureSandboxContainer(params: {
createdAtMs: now, createdAtMs: now,
lastUsedAtMs: now, lastUsedAtMs: now,
image: params.cfg.docker.image, image: params.cfg.docker.image,
configHash: hashMismatch && running ? currentHash ?? undefined : expectedHash, configHash: hashMismatch && running ? (currentHash ?? undefined) : expectedHash,
}); });
return containerName; return containerName;
} }

View File

@@ -6,12 +6,7 @@ import { sessionsCommand } from "../../commands/sessions.js";
import { statusCommand } from "../../commands/status.js"; import { statusCommand } from "../../commands/status.js";
import { setVerbose } from "../../globals.js"; import { setVerbose } from "../../globals.js";
import { defaultRuntime } from "../../runtime.js"; import { defaultRuntime } from "../../runtime.js";
import { import { getFlagValue, getPositiveIntFlagValue, getVerboseFlag, hasFlag } from "../argv.js";
getFlagValue,
getPositiveIntFlagValue,
getVerboseFlag,
hasFlag,
} from "../argv.js";
import { registerBrowserCli } from "../browser-cli.js"; import { registerBrowserCli } from "../browser-cli.js";
import { registerConfigCli } from "../config-cli.js"; import { registerConfigCli } from "../config-cli.js";
import { registerMemoryCli, runMemoryStatus } from "../memory-cli.js"; import { registerMemoryCli, runMemoryStatus } from "../memory-cli.js";

View File

@@ -139,10 +139,12 @@ export const AgentDefaultsSchema = z
model: z model: z
.union([ .union([
z.string(), z.string(),
z.object({ z
primary: z.string().optional(), .object({
fallbacks: z.array(z.string()).optional(), primary: z.string().optional(),
}).strict(), fallbacks: z.array(z.string()).optional(),
})
.strict(),
]) ])
.optional(), .optional(),
}) })

View File

@@ -67,10 +67,12 @@ export const SandboxDockerSchema = z
z.union([ z.union([
z.string(), z.string(),
z.number(), z.number(),
z.object({ z
soft: z.number().int().nonnegative().optional(), .object({
hard: z.number().int().nonnegative().optional(), soft: z.number().int().nonnegative().optional(),
}).strict(), hard: z.number().int().nonnegative().optional(),
})
.strict(),
]), ]),
) )
.optional(), .optional(),
@@ -334,35 +336,37 @@ export const AgentModelSchema = z.union([
]); ]);
export const AgentEntrySchema = z export const AgentEntrySchema = z
.object({ .object({
id: z.string(), id: z.string(),
default: z.boolean().optional(), default: z.boolean().optional(),
name: z.string().optional(), name: z.string().optional(),
workspace: z.string().optional(), workspace: z.string().optional(),
agentDir: z.string().optional(), agentDir: z.string().optional(),
model: AgentModelSchema.optional(), model: AgentModelSchema.optional(),
memorySearch: MemorySearchSchema, memorySearch: MemorySearchSchema,
humanDelay: HumanDelaySchema.optional(), humanDelay: HumanDelaySchema.optional(),
heartbeat: HeartbeatSchema, heartbeat: HeartbeatSchema,
identity: IdentitySchema, identity: IdentitySchema,
groupChat: GroupChatSchema, groupChat: GroupChatSchema,
subagents: z subagents: z
.object({ .object({
allowAgents: z.array(z.string()).optional(), allowAgents: z.array(z.string()).optional(),
model: z model: z
.union([ .union([
z.string(), z.string(),
z.object({ z
primary: z.string().optional(), .object({
fallbacks: z.array(z.string()).optional(), primary: z.string().optional(),
}).strict(), fallbacks: z.array(z.string()).optional(),
]) })
.optional(), .strict(),
}) ])
.strict() .optional(),
.optional(), })
sandbox: AgentSandboxSchema, .strict()
tools: AgentToolsSchema, .optional(),
}) sandbox: AgentSandboxSchema,
tools: AgentToolsSchema,
})
.strict(); .strict();
export const ToolsSchema = z export const ToolsSchema = z

View File

@@ -24,35 +24,35 @@ export const ModelCompatSchema = z
export const ModelDefinitionSchema = z export const ModelDefinitionSchema = z
.object({ .object({
id: z.string().min(1), id: z.string().min(1),
name: z.string().min(1), name: z.string().min(1),
api: ModelApiSchema.optional(), api: ModelApiSchema.optional(),
reasoning: z.boolean(), reasoning: z.boolean(),
input: z.array(z.union([z.literal("text"), z.literal("image")])), input: z.array(z.union([z.literal("text"), z.literal("image")])),
cost: z cost: z
.object({ .object({
input: z.number(), input: z.number(),
output: z.number(), output: z.number(),
cacheRead: z.number(), cacheRead: z.number(),
cacheWrite: z.number(), cacheWrite: z.number(),
}) })
.strict(), .strict(),
contextWindow: z.number().positive(), contextWindow: z.number().positive(),
maxTokens: z.number().positive(), maxTokens: z.number().positive(),
headers: z.record(z.string(), z.string()).optional(), headers: z.record(z.string(), z.string()).optional(),
compat: ModelCompatSchema, compat: ModelCompatSchema,
}) })
.strict(); .strict();
export const ModelProviderSchema = z export const ModelProviderSchema = z
.object({ .object({
baseUrl: z.string().min(1), baseUrl: z.string().min(1),
apiKey: z.string().optional(), apiKey: z.string().optional(),
api: ModelApiSchema.optional(), api: ModelApiSchema.optional(),
headers: z.record(z.string(), z.string()).optional(), headers: z.record(z.string(), z.string()).optional(),
authHeader: z.boolean().optional(), authHeader: z.boolean().optional(),
models: z.array(ModelDefinitionSchema), models: z.array(ModelDefinitionSchema),
}) })
.strict(); .strict();
export const ModelsConfigSchema = z export const ModelsConfigSchema = z
@@ -151,7 +151,9 @@ export const CliBackendSchema = z
sessionArg: z.string().optional(), sessionArg: z.string().optional(),
sessionArgs: z.array(z.string()).optional(), sessionArgs: z.array(z.string()).optional(),
resumeArgs: z.array(z.string()).optional(), resumeArgs: z.array(z.string()).optional(),
sessionMode: z.union([z.literal("always"), z.literal("existing"), z.literal("none")]).optional(), sessionMode: z
.union([z.literal("always"), z.literal("existing"), z.literal("none")])
.optional(),
sessionIdFields: z.array(z.string()).optional(), sessionIdFields: z.array(z.string()).optional(),
systemPromptArg: z.string().optional(), systemPromptArg: z.string().optional(),
systemPromptMode: z.union([z.literal("append"), z.literal("replace")]).optional(), systemPromptMode: z.union([z.literal("append"), z.literal("replace")]).optional(),

View File

@@ -79,46 +79,46 @@ const validateTelegramCustomCommands = (
export const TelegramAccountSchemaBase = z export const TelegramAccountSchemaBase = z
.object({ .object({
name: z.string().optional(), name: z.string().optional(),
capabilities: TelegramCapabilitiesSchema.optional(), capabilities: TelegramCapabilitiesSchema.optional(),
enabled: z.boolean().optional(), enabled: z.boolean().optional(),
commands: ProviderCommandsSchema, commands: ProviderCommandsSchema,
customCommands: z.array(TelegramCustomCommandSchema).optional(), customCommands: z.array(TelegramCustomCommandSchema).optional(),
configWrites: z.boolean().optional(), configWrites: z.boolean().optional(),
dmPolicy: DmPolicySchema.optional().default("pairing"), dmPolicy: DmPolicySchema.optional().default("pairing"),
botToken: z.string().optional(), botToken: z.string().optional(),
tokenFile: z.string().optional(), tokenFile: z.string().optional(),
replyToMode: ReplyToModeSchema.optional(), replyToMode: ReplyToModeSchema.optional(),
groups: z.record(z.string(), TelegramGroupSchema.optional()).optional(), groups: z.record(z.string(), TelegramGroupSchema.optional()).optional(),
allowFrom: z.array(z.union([z.string(), z.number()])).optional(), allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(), groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
groupPolicy: GroupPolicySchema.optional().default("allowlist"), groupPolicy: GroupPolicySchema.optional().default("allowlist"),
historyLimit: z.number().int().min(0).optional(), historyLimit: z.number().int().min(0).optional(),
dmHistoryLimit: z.number().int().min(0).optional(), dmHistoryLimit: z.number().int().min(0).optional(),
dms: z.record(z.string(), DmConfigSchema.optional()).optional(), dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(), blockStreaming: z.boolean().optional(),
draftChunk: BlockStreamingChunkSchema.optional(), draftChunk: BlockStreamingChunkSchema.optional(),
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(), blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
streamMode: z.enum(["off", "partial", "block"]).optional().default("partial"), streamMode: z.enum(["off", "partial", "block"]).optional().default("partial"),
mediaMaxMb: z.number().positive().optional(), mediaMaxMb: z.number().positive().optional(),
timeoutSeconds: z.number().int().positive().optional(), timeoutSeconds: z.number().int().positive().optional(),
retry: RetryConfigSchema, retry: RetryConfigSchema,
proxy: z.string().optional(), proxy: z.string().optional(),
webhookUrl: z.string().optional(), webhookUrl: z.string().optional(),
webhookSecret: z.string().optional(), webhookSecret: z.string().optional(),
webhookPath: z.string().optional(), webhookPath: z.string().optional(),
actions: z actions: z
.object({ .object({
reactions: z.boolean().optional(), reactions: z.boolean().optional(),
sendMessage: z.boolean().optional(), sendMessage: z.boolean().optional(),
deleteMessage: z.boolean().optional(), deleteMessage: z.boolean().optional(),
}) })
.strict() .strict()
.optional(), .optional(),
reactionNotifications: z.enum(["off", "own", "all"]).optional(), reactionNotifications: z.enum(["off", "own", "all"]).optional(),
reactionLevel: z.enum(["off", "ack", "minimal", "extensive"]).optional(), reactionLevel: z.enum(["off", "ack", "minimal", "extensive"]).optional(),
}) })
.strict(); .strict();
export const TelegramAccountSchema = TelegramAccountSchemaBase.superRefine((value, ctx) => { export const TelegramAccountSchema = TelegramAccountSchemaBase.superRefine((value, ctx) => {
@@ -191,50 +191,50 @@ export const DiscordGuildSchema = z
export const DiscordAccountSchema = z export const DiscordAccountSchema = z
.object({ .object({
name: z.string().optional(), name: z.string().optional(),
capabilities: z.array(z.string()).optional(), capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(), enabled: z.boolean().optional(),
commands: ProviderCommandsSchema, commands: ProviderCommandsSchema,
configWrites: z.boolean().optional(), configWrites: z.boolean().optional(),
token: z.string().optional(), token: z.string().optional(),
allowBots: z.boolean().optional(), allowBots: z.boolean().optional(),
groupPolicy: GroupPolicySchema.optional().default("allowlist"), groupPolicy: GroupPolicySchema.optional().default("allowlist"),
historyLimit: z.number().int().min(0).optional(), historyLimit: z.number().int().min(0).optional(),
dmHistoryLimit: z.number().int().min(0).optional(), dmHistoryLimit: z.number().int().min(0).optional(),
dms: z.record(z.string(), DmConfigSchema.optional()).optional(), dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(), blockStreaming: z.boolean().optional(),
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(), blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
maxLinesPerMessage: z.number().int().positive().optional(), maxLinesPerMessage: z.number().int().positive().optional(),
mediaMaxMb: z.number().positive().optional(), mediaMaxMb: z.number().positive().optional(),
retry: RetryConfigSchema, retry: RetryConfigSchema,
actions: z actions: z
.object({ .object({
reactions: z.boolean().optional(), reactions: z.boolean().optional(),
stickers: z.boolean().optional(), stickers: z.boolean().optional(),
emojiUploads: z.boolean().optional(), emojiUploads: z.boolean().optional(),
stickerUploads: z.boolean().optional(), stickerUploads: z.boolean().optional(),
polls: z.boolean().optional(), polls: z.boolean().optional(),
permissions: z.boolean().optional(), permissions: z.boolean().optional(),
messages: z.boolean().optional(), messages: z.boolean().optional(),
threads: z.boolean().optional(), threads: z.boolean().optional(),
pins: z.boolean().optional(), pins: z.boolean().optional(),
search: z.boolean().optional(), search: z.boolean().optional(),
memberInfo: z.boolean().optional(), memberInfo: z.boolean().optional(),
roleInfo: z.boolean().optional(), roleInfo: z.boolean().optional(),
roles: z.boolean().optional(), roles: z.boolean().optional(),
channelInfo: z.boolean().optional(), channelInfo: z.boolean().optional(),
voiceStatus: z.boolean().optional(), voiceStatus: z.boolean().optional(),
events: z.boolean().optional(), events: z.boolean().optional(),
moderation: z.boolean().optional(), moderation: z.boolean().optional(),
channels: z.boolean().optional(), channels: z.boolean().optional(),
}) })
.strict() .strict()
.optional(), .optional(),
replyToMode: ReplyToModeSchema.optional(), replyToMode: ReplyToModeSchema.optional(),
dm: DiscordDmSchema.optional(), dm: DiscordDmSchema.optional(),
guilds: z.record(z.string(), DiscordGuildSchema.optional()).optional(), guilds: z.record(z.string(), DiscordGuildSchema.optional()).optional(),
}) })
.strict(); .strict();
export const DiscordConfigSchema = DiscordAccountSchema.extend({ export const DiscordConfigSchema = DiscordAccountSchema.extend({
@@ -282,57 +282,57 @@ export const SlackThreadSchema = z
export const SlackAccountSchema = z export const SlackAccountSchema = z
.object({ .object({
name: z.string().optional(), name: z.string().optional(),
mode: z.enum(["socket", "http"]).optional(), mode: z.enum(["socket", "http"]).optional(),
signingSecret: z.string().optional(), signingSecret: z.string().optional(),
webhookPath: z.string().optional(), webhookPath: z.string().optional(),
capabilities: z.array(z.string()).optional(), capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(), enabled: z.boolean().optional(),
commands: ProviderCommandsSchema, commands: ProviderCommandsSchema,
configWrites: z.boolean().optional(), configWrites: z.boolean().optional(),
botToken: z.string().optional(), botToken: z.string().optional(),
appToken: z.string().optional(), appToken: z.string().optional(),
userToken: z.string().optional(), userToken: z.string().optional(),
userTokenReadOnly: z.boolean().optional().default(true), userTokenReadOnly: z.boolean().optional().default(true),
allowBots: z.boolean().optional(), allowBots: z.boolean().optional(),
requireMention: z.boolean().optional(), requireMention: z.boolean().optional(),
groupPolicy: GroupPolicySchema.optional().default("allowlist"), groupPolicy: GroupPolicySchema.optional().default("allowlist"),
historyLimit: z.number().int().min(0).optional(), historyLimit: z.number().int().min(0).optional(),
dmHistoryLimit: z.number().int().min(0).optional(), dmHistoryLimit: z.number().int().min(0).optional(),
dms: z.record(z.string(), DmConfigSchema.optional()).optional(), dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(), blockStreaming: z.boolean().optional(),
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(), blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
mediaMaxMb: z.number().positive().optional(), mediaMaxMb: z.number().positive().optional(),
reactionNotifications: z.enum(["off", "own", "all", "allowlist"]).optional(), reactionNotifications: z.enum(["off", "own", "all", "allowlist"]).optional(),
reactionAllowlist: z.array(z.union([z.string(), z.number()])).optional(), reactionAllowlist: z.array(z.union([z.string(), z.number()])).optional(),
replyToMode: ReplyToModeSchema.optional(), replyToMode: ReplyToModeSchema.optional(),
thread: SlackThreadSchema.optional(), thread: SlackThreadSchema.optional(),
actions: z actions: z
.object({ .object({
reactions: z.boolean().optional(), reactions: z.boolean().optional(),
messages: z.boolean().optional(), messages: z.boolean().optional(),
pins: z.boolean().optional(), pins: z.boolean().optional(),
search: z.boolean().optional(), search: z.boolean().optional(),
permissions: z.boolean().optional(), permissions: z.boolean().optional(),
memberInfo: z.boolean().optional(), memberInfo: z.boolean().optional(),
channelInfo: z.boolean().optional(), channelInfo: z.boolean().optional(),
emojiList: z.boolean().optional(), emojiList: z.boolean().optional(),
}) })
.strict() .strict()
.optional(), .optional(),
slashCommand: z slashCommand: z
.object({ .object({
enabled: z.boolean().optional(), enabled: z.boolean().optional(),
name: z.string().optional(), name: z.string().optional(),
sessionPrefix: z.string().optional(), sessionPrefix: z.string().optional(),
ephemeral: z.boolean().optional(), ephemeral: z.boolean().optional(),
}) })
.strict() .strict()
.optional(), .optional(),
dm: SlackDmSchema.optional(), dm: SlackDmSchema.optional(),
channels: z.record(z.string(), SlackChannelSchema.optional()).optional(), channels: z.record(z.string(), SlackChannelSchema.optional()).optional(),
}) })
.strict(); .strict();
export const SlackConfigSchema = SlackAccountSchema.extend({ export const SlackConfigSchema = SlackAccountSchema.extend({
@@ -369,34 +369,34 @@ export const SlackConfigSchema = SlackAccountSchema.extend({
export const SignalAccountSchemaBase = z export const SignalAccountSchemaBase = z
.object({ .object({
name: z.string().optional(), name: z.string().optional(),
capabilities: z.array(z.string()).optional(), capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(), enabled: z.boolean().optional(),
configWrites: z.boolean().optional(), configWrites: z.boolean().optional(),
account: z.string().optional(), account: z.string().optional(),
httpUrl: z.string().optional(), httpUrl: z.string().optional(),
httpHost: z.string().optional(), httpHost: z.string().optional(),
httpPort: z.number().int().positive().optional(), httpPort: z.number().int().positive().optional(),
cliPath: ExecutableTokenSchema.optional(), cliPath: ExecutableTokenSchema.optional(),
autoStart: z.boolean().optional(), autoStart: z.boolean().optional(),
receiveMode: z.union([z.literal("on-start"), z.literal("manual")]).optional(), receiveMode: z.union([z.literal("on-start"), z.literal("manual")]).optional(),
ignoreAttachments: z.boolean().optional(), ignoreAttachments: z.boolean().optional(),
ignoreStories: z.boolean().optional(), ignoreStories: z.boolean().optional(),
sendReadReceipts: z.boolean().optional(), sendReadReceipts: z.boolean().optional(),
dmPolicy: DmPolicySchema.optional().default("pairing"), dmPolicy: DmPolicySchema.optional().default("pairing"),
allowFrom: z.array(z.union([z.string(), z.number()])).optional(), allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(), groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
groupPolicy: GroupPolicySchema.optional().default("allowlist"), groupPolicy: GroupPolicySchema.optional().default("allowlist"),
historyLimit: z.number().int().min(0).optional(), historyLimit: z.number().int().min(0).optional(),
dmHistoryLimit: z.number().int().min(0).optional(), dmHistoryLimit: z.number().int().min(0).optional(),
dms: z.record(z.string(), DmConfigSchema.optional()).optional(), dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(), blockStreaming: z.boolean().optional(),
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(), blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
mediaMaxMb: z.number().int().positive().optional(), mediaMaxMb: z.number().int().positive().optional(),
reactionNotifications: z.enum(["off", "own", "all", "allowlist"]).optional(), reactionNotifications: z.enum(["off", "own", "all", "allowlist"]).optional(),
reactionAllowlist: z.array(z.union([z.string(), z.number()])).optional(), reactionAllowlist: z.array(z.union([z.string(), z.number()])).optional(),
}) })
.strict(); .strict();
export const SignalAccountSchema = SignalAccountSchemaBase.superRefine((value, ctx) => { export const SignalAccountSchema = SignalAccountSchemaBase.superRefine((value, ctx) => {
@@ -423,39 +423,39 @@ export const SignalConfigSchema = SignalAccountSchemaBase.extend({
export const IMessageAccountSchemaBase = z export const IMessageAccountSchemaBase = z
.object({ .object({
name: z.string().optional(), name: z.string().optional(),
capabilities: z.array(z.string()).optional(), capabilities: z.array(z.string()).optional(),
enabled: z.boolean().optional(), enabled: z.boolean().optional(),
configWrites: z.boolean().optional(), configWrites: z.boolean().optional(),
cliPath: ExecutableTokenSchema.optional(), cliPath: ExecutableTokenSchema.optional(),
dbPath: z.string().optional(), dbPath: z.string().optional(),
remoteHost: z.string().optional(), remoteHost: z.string().optional(),
service: z.union([z.literal("imessage"), z.literal("sms"), z.literal("auto")]).optional(), service: z.union([z.literal("imessage"), z.literal("sms"), z.literal("auto")]).optional(),
region: z.string().optional(), region: z.string().optional(),
dmPolicy: DmPolicySchema.optional().default("pairing"), dmPolicy: DmPolicySchema.optional().default("pairing"),
allowFrom: z.array(z.union([z.string(), z.number()])).optional(), allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(), groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
groupPolicy: GroupPolicySchema.optional().default("allowlist"), groupPolicy: GroupPolicySchema.optional().default("allowlist"),
historyLimit: z.number().int().min(0).optional(), historyLimit: z.number().int().min(0).optional(),
dmHistoryLimit: z.number().int().min(0).optional(), dmHistoryLimit: z.number().int().min(0).optional(),
dms: z.record(z.string(), DmConfigSchema.optional()).optional(), dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
includeAttachments: z.boolean().optional(), includeAttachments: z.boolean().optional(),
mediaMaxMb: z.number().int().positive().optional(), mediaMaxMb: z.number().int().positive().optional(),
textChunkLimit: z.number().int().positive().optional(), textChunkLimit: z.number().int().positive().optional(),
blockStreaming: z.boolean().optional(), blockStreaming: z.boolean().optional(),
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(), blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
groups: z groups: z
.record( .record(
z.string(), z.string(),
z z
.object({ .object({
requireMention: z.boolean().optional(), requireMention: z.boolean().optional(),
}) })
.strict() .strict()
.optional(), .optional(),
) )
.optional(), .optional(),
}) })
.strict(); .strict();
export const IMessageAccountSchema = IMessageAccountSchemaBase.superRefine((value, ctx) => { export const IMessageAccountSchema = IMessageAccountSchemaBase.superRefine((value, ctx) => {

View File

@@ -429,9 +429,7 @@ async function migrateLegacySessions(
await saveSessionStore(detected.sessions.targetStorePath, normalized); await saveSessionStore(detected.sessions.targetStorePath, normalized);
changes.push(`Merged sessions store → ${detected.sessions.targetStorePath}`); changes.push(`Merged sessions store → ${detected.sessions.targetStorePath}`);
if (canonicalizedTarget.legacyKeys.length > 0) { if (canonicalizedTarget.legacyKeys.length > 0) {
changes.push( changes.push(`Canonicalized ${canonicalizedTarget.legacyKeys.length} legacy session key(s)`);
`Canonicalized ${canonicalizedTarget.legacyKeys.length} legacy session key(s)`,
);
} }
} }