diff --git a/.oxlintrc.json b/.oxlintrc.json index 3876f8e04..4d85dff76 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -6,7 +6,14 @@ "oxc" ], "categories": { - "correctness": "error" + "correctness": "error", + "perf": "error" + }, + "rules": { + "eslint-plugin-unicorn/prefer-array-find": "off", + "eslint/no-await-in-loop": "off", + "oxc/no-accumulating-spread": "off", + "oxc/no-map-spread": "off" }, "ignorePatterns": ["src/canvas-host/a2ui/a2ui.bundle.js"] } diff --git a/src/agents/auth-health.ts b/src/agents/auth-health.ts index 4f281b7bb..4301c8a71 100644 --- a/src/agents/auth-health.ts +++ b/src/agents/auth-health.ts @@ -226,10 +226,10 @@ export function buildAuthHealthSummary(params: { provider.remainingMs = provider.expiresAt - now; } - const statuses = expirable.map((p) => p.status); - if (statuses.includes("expired") || statuses.includes("missing")) { + const statuses = new Set(expirable.map((p) => p.status)); + if (statuses.has("expired") || statuses.has("missing")) { provider.status = "expired"; - } else if (statuses.includes("expiring")) { + } else if (statuses.has("expiring")) { provider.status = "expiring"; } else { provider.status = "ok"; diff --git a/src/auto-reply/reply/model-selection.ts b/src/auto-reply/reply/model-selection.ts index 06df2d9b0..e970592e0 100644 --- a/src/auto-reply/reply/model-selection.ts +++ b/src/auto-reply/reply/model-selection.ts @@ -434,7 +434,7 @@ export function resolveModelDirectiveSelection(params: { defaultProvider, defaultModel, }); - return { candidate, ...details }; + return Object.assign({ candidate }, details); }) .sort((a, b) => { if (b.score !== a.score) return b.score - a.score; diff --git a/src/daemon/service-audit.ts b/src/daemon/service-audit.ts index 20ddd4ff2..0754e906f 100644 --- a/src/daemon/service-audit.ts +++ b/src/daemon/service-audit.ts @@ -225,11 +225,11 @@ function auditGatewayServicePath( .split(getPathModule(platform).delimiter) .map((entry) => entry.trim()) .filter(Boolean); - const normalizedParts = parts.map((entry) => normalizePathEntry(entry, platform)); + const normalizedParts = new Set(parts.map((entry) => normalizePathEntry(entry, platform))); const normalizedExpected = new Set(expected.map((entry) => normalizePathEntry(entry, platform))); const missing = expected.filter((entry) => { const normalized = normalizePathEntry(entry, platform); - return !normalizedParts.includes(normalized); + return !normalizedParts.has(normalized); }); if (missing.length > 0) { issues.push({ diff --git a/src/discord/monitor/allow-list.ts b/src/discord/monitor/allow-list.ts index 12c2d1d39..b3836fe96 100644 --- a/src/discord/monitor/allow-list.ts +++ b/src/discord/monitor/allow-list.ts @@ -331,13 +331,13 @@ export function resolveGroupDmAllow(params: { }) { const { channels, channelId, channelName, channelSlug } = params; if (!channels || channels.length === 0) return true; - const allowList = channels.map((entry) => normalizeDiscordSlug(String(entry))); + const allowList = new Set(channels.map((entry) => normalizeDiscordSlug(String(entry)))); const candidates = [ normalizeDiscordSlug(channelId), channelSlug, channelName ? normalizeDiscordSlug(channelName) : "", ].filter(Boolean); - return allowList.includes("*") || candidates.some((candidate) => allowList.includes(candidate)); + return allowList.has("*") || candidates.some((candidate) => allowList.has(candidate)); } export function shouldEmitDiscordReactionNotification(params: { diff --git a/src/infra/session-cost-usage.ts b/src/infra/session-cost-usage.ts index 28cbaa0b2..aaa34c8c8 100644 --- a/src/infra/session-cost-usage.ts +++ b/src/infra/session-cost-usage.ts @@ -218,7 +218,7 @@ export async function loadCostUsageSummary(params?: { } const daily = Array.from(dailyMap.entries()) - .map(([date, bucket]) => ({ date, ...bucket })) + .map(([date, bucket]) => Object.assign({ date }, bucket)) .sort((a, b) => a.date.localeCompare(b.date)); return { diff --git a/src/memory/manager.ts b/src/memory/manager.ts index aa3cb317d..1ad3378a4 100644 --- a/src/memory/manager.ts +++ b/src/memory/manager.ts @@ -527,7 +527,7 @@ export class MemoryIndexManager { entry.chunks = row.c ?? 0; bySource.set(row.source, entry); } - return sources.map((source) => ({ source, ...bySource.get(source)! })); + return sources.map((source) => Object.assign({ source }, bySource.get(source)!)); })(); return { files: files?.c ?? 0, diff --git a/src/telegram/bot.test.ts b/src/telegram/bot.test.ts index 8129adc7a..e2c775a11 100644 --- a/src/telegram/bot.test.ts +++ b/src/telegram/bot.test.ts @@ -310,8 +310,8 @@ describe("createTelegramBot", () => { { command: "custom_backup", description: "Git backup" }, { command: "custom_generate", description: "Create an image" }, ]); - const reserved = listNativeCommandSpecs().map((command) => command.name); - expect(registered.some((command) => reserved.includes(command.command))).toBe(false); + const reserved = new Set(listNativeCommandSpecs().map((command) => command.name)); + expect(registered.some((command) => reserved.has(command.command))).toBe(false); }); it("uses wrapped fetch when global fetch is available", () => {