File size: 4,760 Bytes
921d377
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
 * Backend URL resolution.
 *
 * On a local dev machine (vite dev server on :5173) the backend runs on a
 * different port, so we default to ``http://localhost:8000``.
 *
 * On a deployed environment (Hugging Face Space, Docker, etc.) the backend
 * and frontend share the same origin, so we default to ``window.location.origin``.
 *
 * Priority (first match wins):
 *   1. Explicit user setting (``localStorage.homepilot_backend_url``) —
 *      ignored when it points at a local dev host but the page is served
 *      from a remote host (stale leftover from an earlier session).
 *   2. Build-time env (``VITE_API_URL``)
 *   3. Current origin when served from a non-dev host
 *   4. ``http://localhost:8000`` fallback
 *
 * Always returns a value with no trailing slash.
 */
const LOCAL_HOSTS = new Set(["localhost", "127.0.0.1", "0.0.0.0", "::1"]);
// Vite dev ports used across the repo. The Makefile's `make start` target
// launches vite with --port 3000; earlier tooling used Vite's defaults
// 5173/5174. All of them must route API traffic to the backend at :8000
// rather than to the Vite origin (which would SPA-fallback every request
// to index.html and break JSON.parse).
const DEV_VITE_PORTS = new Set(["3000", "5173", "5174"]);
function isLocalHost(hostname) {
    return LOCAL_HOSTS.has(hostname);
}
function parsedHostname(url) {
    try {
        return new URL(url).hostname;
    }
    catch {
        return null;
    }
}
/** Best default when nothing else is configured — based on current location. */
export function getDefaultBackendUrl() {
    if (typeof window === "undefined") {
        return "http://localhost:8000";
    }
    const env = import.meta.env?.VITE_API_URL?.trim();
    if (env)
        return stripTrailingSlash(env);
    const { hostname, origin, port } = window.location;
    // On the Vite dev server the backend is a separate process on :8000.
    if (isLocalHost(hostname) && DEV_VITE_PORTS.has(port)) {
        return "http://localhost:8000";
    }
    // Everywhere else — deployed Spaces, Docker, preview builds — the frontend
    // is served by the backend itself, so same-origin is always correct.
    return stripTrailingSlash(origin);
}
/**
 * Resolve the user-configured or default backend URL. Use this anywhere the
 * old hardcoded fallback ``'http://localhost:8000'`` was written.
 *
 * Robustness: if the stored value points at a localhost backend but the
 * page itself is served from a remote host (common after upgrades), we
 * ignore the stale setting and fall through to the current origin. This
 * fixes the "Failed to fetch" storm users hit after first deploy.
 */
export function resolveBackendUrl(override) {
    if (typeof override === "string" && override.trim()) {
        return stripTrailingSlash(override.trim());
    }
    if (typeof window !== "undefined") {
        try {
            const stored = window.localStorage.getItem("homepilot_backend_url");
            if (stored && stored.trim()) {
                const clean = stripTrailingSlash(stored.trim());
                const pageIsRemote = !isLocalHost(window.location.hostname);
                const storedUrl = (() => { try {
                    return new URL(clean);
                }
                catch {
                    return null;
                } })();
                const storedHost = storedUrl?.hostname ?? null;
                const storedPort = storedUrl?.port ?? "";
                const storedIsLocal = storedHost !== null && isLocalHost(storedHost);
                if (pageIsRemote && storedIsLocal) {
                    // Stale setting from a previous local dev session. Ignore it and
                    // let getDefaultBackendUrl() take over (same origin).
                    return getDefaultBackendUrl();
                }
                // Stale setting pointing at a Vite DEV port on localhost (3000 / 5173
                // / 5174). The frontend origin serves the SPA — POSTing JSON there
                // SPA-falls-back to index.html and the caller sees a 404, which the
                // voice-call path reads as "feature unavailable" and flips to the
                // chat-REST fallback. Redirect to :8000 (the default backend port)
                // so the stored preference doesn't silently break voice-call
                // session creation.
                if (storedIsLocal && DEV_VITE_PORTS.has(storedPort)) {
                    return "http://localhost:8000";
                }
                return clean;
            }
        }
        catch {
            /* localStorage unavailable — fall through to default */
        }
    }
    return getDefaultBackendUrl();
}
function stripTrailingSlash(url) {
    return url.replace(/\/+$/, "");
}