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];