diff --git a/open-sse/services/combo.ts b/open-sse/services/combo.ts
index ea56cb5c60..ca08f3a17d 100644
--- a/open-sse/services/combo.ts
+++ b/open-sse/services/combo.ts
@@ -1944,7 +1944,11 @@ async function handleRoundRobinCombo({
// Extract error info
let errorText = result.statusText || "";
let retryAfter = null;
- let errorBody: { error?: { code?: string | null; message?: string | null } } | null = null;
+ let errorBody: {
+ error?: { code?: string | null; message?: string | null } | string;
+ message?: string | null;
+ retryAfter?: number | string | null;
+ } | null = null;
try {
const cloned = result.clone();
try {
diff --git a/src/app/(dashboard)/dashboard/batch/page.tsx b/src/app/(dashboard)/dashboard/batch/page.tsx
index 9e9fe12f69..0743a7442f 100644
--- a/src/app/(dashboard)/dashboard/batch/page.tsx
+++ b/src/app/(dashboard)/dashboard/batch/page.tsx
@@ -1,9 +1,18 @@
"use client";
import { useState, useEffect } from "react";
-import Card from "@/shared/components/Card";
-import EmptyState from "@/shared/components/EmptyState";
-import { formatDistanceToNow } from "date-fns";
+import { Card, EmptyState } from "@/shared/components";
+
+function formatDistanceToNow(timestamp: number) {
+ const seconds = Math.floor(Date.now() / 1000 - timestamp);
+ if (seconds < 60) return `${seconds}s ago`;
+ const minutes = Math.floor(seconds / 60);
+ if (minutes < 60) return `${minutes}m ago`;
+ const hours = Math.floor(minutes / 60);
+ if (hours < 24) return `${hours}h ago`;
+ const days = Math.floor(hours / 24);
+ return `${days}d ago`;
+}
export default function BatchPage() {
const [batches, setBatches] = useState([]);
@@ -70,7 +79,7 @@ export default function BatchPage() {
- {formatDistanceToNow(batch.createdAt, { addSuffix: true })}
+ {formatDistanceToNow(batch.createdAt)}
@@ -121,9 +130,7 @@ export default function BatchPage() {
{file.id}
-
- {formatDistanceToNow(file.createdAt, { addSuffix: true })}
-
+ {formatDistanceToNow(file.createdAt)}
diff --git a/src/app/api/providers/[id]/models/route.ts b/src/app/api/providers/[id]/models/route.ts
index 5503b047cd..c19bbb67ef 100755
--- a/src/app/api/providers/[id]/models/route.ts
+++ b/src/app/api/providers/[id]/models/route.ts
@@ -1,12 +1,15 @@
import { NextResponse } from "next/server";
-import { getProviderConnectionById } from "@/models";
import {
isClaudeCodeCompatibleProvider,
isOpenAICompatibleProvider,
isAnthropicCompatibleProvider,
} from "@/shared/constants/providers";
import { PROVIDER_MODELS } from "@/shared/constants/models";
-import { getModelIsHidden, resolveProxyForProvider } from "@/lib/localDb";
+import {
+ getProviderConnectionById,
+ getModelIsHidden,
+ resolveProxyForProvider,
+} from "@/lib/localDb";
import {
SAFE_OUTBOUND_FETCH_PRESETS,
getSafeOutboundFetchErrorStatus,
diff --git a/src/lib/dataPaths.js b/src/lib/dataPaths.js
new file mode 100644
index 0000000000..5078bbe9e6
--- /dev/null
+++ b/src/lib/dataPaths.js
@@ -0,0 +1,66 @@
+"use strict";
+var __importDefault =
+ (this && this.__importDefault) ||
+ function (mod) {
+ return mod && mod.__esModule ? mod : { default: mod };
+ };
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.APP_NAME = void 0;
+exports.getLegacyDotDataDir = getLegacyDotDataDir;
+exports.getDefaultDataDir = getDefaultDataDir;
+exports.resolveDataDir = resolveDataDir;
+exports.isSamePath = isSamePath;
+const path_1 = __importDefault(require("path"));
+const os_1 = __importDefault(require("os"));
+exports.APP_NAME = "omniroute";
+function fallbackHomeDir() {
+ const envHome = process.env.HOME || process.env.USERPROFILE;
+ if (typeof envHome === "string" && envHome.trim().length > 0) {
+ return path_1.default.resolve(envHome);
+ }
+ return os_1.default.tmpdir();
+}
+function safeHomeDir() {
+ try {
+ return os_1.default.homedir();
+ } catch {
+ return fallbackHomeDir();
+ }
+}
+function normalizeConfiguredPath(dir) {
+ if (typeof dir !== "string") return null;
+ const trimmed = dir.trim();
+ if (!trimmed) return null;
+ return path_1.default.resolve(trimmed);
+}
+function getLegacyDotDataDir() {
+ return path_1.default.join(safeHomeDir(), `.${exports.APP_NAME}`);
+}
+function getDefaultDataDir() {
+ const homeDir = safeHomeDir();
+ if (process.platform === "win32") {
+ const appData = process.env.APPDATA || path_1.default.join(homeDir, "AppData", "Roaming");
+ return path_1.default.join(appData, exports.APP_NAME);
+ }
+ // Support XDG on Linux/macOS when explicitly configured.
+ const xdgConfigHome = normalizeConfiguredPath(process.env.XDG_CONFIG_HOME);
+ if (xdgConfigHome) {
+ return path_1.default.join(xdgConfigHome, exports.APP_NAME);
+ }
+ return getLegacyDotDataDir();
+}
+function resolveDataDir({ isCloud = false } = {}) {
+ if (isCloud) return "/tmp";
+ const configured = normalizeConfiguredPath(process.env.DATA_DIR);
+ if (configured) return configured;
+ return getDefaultDataDir();
+}
+function isSamePath(a, b) {
+ if (!a || !b) return false;
+ const normalizedA = path_1.default.resolve(a);
+ const normalizedB = path_1.default.resolve(b);
+ if (process.platform === "win32") {
+ return normalizedA.toLowerCase() === normalizedB.toLowerCase();
+ }
+ return normalizedA === normalizedB;
+}
diff --git a/tests/scratch_test.mjs b/tests/scratch_test.mjs
new file mode 100644
index 0000000000..a2cccf40c4
--- /dev/null
+++ b/tests/scratch_test.mjs
@@ -0,0 +1,4 @@
+import { getDbInstance } from "../src/lib/db/core.ts";
+import { runMigrations, getMigrationStatus } from "../src/lib/db/migrationRunner.ts";
+const db = getDbInstance();
+console.log(getMigrationStatus(db).pending);
diff --git a/tests/unit/prompt-injection-guard.test.ts b/tests/unit/prompt-injection-guard.test.ts
index ea3b41bcad..b0975950f5 100644
--- a/tests/unit/prompt-injection-guard.test.ts
+++ b/tests/unit/prompt-injection-guard.test.ts
@@ -6,8 +6,8 @@ import {
withInjectionGuard,
} from "../../src/middleware/promptInjectionGuard.ts";
-async function withEnv(overrides, fn) {
- const originals = {};
+async function withEnv(overrides: Record, fn: any) {
+ const originals: Record = {};
for (const [key, value] of Object.entries(overrides)) {
originals[key] = process.env[key];