orionfold-relay 0.15.4 → 0.15.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -25235,8 +25235,8 @@ import { execFileSync as execFileSync3 } from "child_process";
|
|
|
25235
25235
|
import yaml12 from "js-yaml";
|
|
25236
25236
|
import semver from "semver";
|
|
25237
25237
|
function relayCoreVersion() {
|
|
25238
|
-
if (semver.valid("0.15.
|
|
25239
|
-
return "0.15.
|
|
25238
|
+
if (semver.valid("0.15.5")) {
|
|
25239
|
+
return "0.15.5";
|
|
25240
25240
|
}
|
|
25241
25241
|
try {
|
|
25242
25242
|
const root = getAppRoot(import.meta.dirname, 3);
|
|
@@ -26049,7 +26049,13 @@ async function main() {
|
|
|
26049
26049
|
RELAY_DATA_DIR: DATA_DIR,
|
|
26050
26050
|
RELAY_LAUNCH_CWD: launchCwd2,
|
|
26051
26051
|
PORT: String(actualPort),
|
|
26052
|
-
...opts.safeMode ? { RELAY_SAFE_MODE: "true" } : {}
|
|
26052
|
+
...opts.safeMode ? { RELAY_SAFE_MODE: "true" } : {},
|
|
26053
|
+
// In dev mode, Next blocks cross-origin /_next/* dev-asset requests from
|
|
26054
|
+
// the LAN client's IP, breaking the app over the network (issue #13).
|
|
26055
|
+
// When the operator has opted into non-loopback binding, tell next.config
|
|
26056
|
+
// to allow any dev origin. Mirrors the same trust decision as the warning
|
|
26057
|
+
// above; harmless for the prebuilt `next start` path (no dev-origin gate).
|
|
26058
|
+
...isNonLoopbackHost(bindHost) ? { RELAY_ALLOW_LAN_ORIGINS: "true" } : {}
|
|
26053
26059
|
}
|
|
26054
26060
|
});
|
|
26055
26061
|
if (opts.open !== false) {
|
package/next.config.mjs
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
|
+
// When the operator opts into LAN binding (`--hostname` to a non-loopback host,
|
|
2
|
+
// see bin/cli.ts), the CLI sets RELAY_ALLOW_LAN_ORIGINS=true. In dev mode Next
|
|
3
|
+
// otherwise blocks cross-origin requests to /_next/* dev assets from the LAN
|
|
4
|
+
// client's IP — which silently breaks the whole app over the network (issue
|
|
5
|
+
// #13). The client IP is unknowable at config-load time (the bind host is
|
|
6
|
+
// 0.0.0.0 = "all interfaces"), and Next's matcher explicitly rejects a bare
|
|
7
|
+
// "*"/"**" catch-all, so we allow every RFC1918 private-network range instead.
|
|
8
|
+
// This matches the "trusted network" assumption the --hostname warning already
|
|
9
|
+
// states, while still blocking public origins. (Prod `next start` has no such
|
|
10
|
+
// gate; this only affects the dev-mode npx path.)
|
|
11
|
+
const RFC1918_DEV_ORIGINS = [
|
|
12
|
+
"10.*.*.*",
|
|
13
|
+
"192.168.*.*",
|
|
14
|
+
// 172.16.0.0/12 — Next's matcher globs per-octet, so enumerate 16–31.
|
|
15
|
+
...Array.from({ length: 16 }, (_, i) => `172.${16 + i}.*.*`),
|
|
16
|
+
];
|
|
17
|
+
const allowLanDevOrigins = process.env.RELAY_ALLOW_LAN_ORIGINS === "true";
|
|
18
|
+
|
|
1
19
|
/** @type {import('next').NextConfig} */
|
|
2
20
|
const nextConfig = {
|
|
3
21
|
serverExternalPackages: ["better-sqlite3", "pdf-parse", "pdfjs-dist"],
|
|
4
22
|
devIndicators: false,
|
|
5
|
-
allowedDevOrigins:
|
|
23
|
+
allowedDevOrigins: allowLanDevOrigins
|
|
24
|
+
? ["127.0.0.1", ...RFC1918_DEV_ORIGINS]
|
|
25
|
+
: ["127.0.0.1"],
|
|
6
26
|
// The in-app kindle reader was removed; the book lives at ainative.business.
|
|
7
27
|
// Redirect legacy /book links (and any chapter-anchored deep links) there.
|
|
8
28
|
async redirects() {
|
package/package.json
CHANGED
package/src/app/layout.tsx
CHANGED
|
@@ -68,7 +68,13 @@ const CRITICAL_THEME_CSS = `
|
|
|
68
68
|
--surface-2: oklch(0.16 0.02 250);
|
|
69
69
|
--border: oklch(0.26 0.015 250);
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
/* Root rem base. Fixed 14px left the whole rem-based design tiny on high-res
|
|
72
|
+
4K displays (issue #4) — text stayed 14px regardless of viewport, forcing
|
|
73
|
+
browser zoom. This clamp holds a flat 14px through 1920px-wide viewports
|
|
74
|
+
(unchanged for existing laptop/desktop users) and only ramps up on QHD/4K:
|
|
75
|
+
~16px at 2560px, capped at 18px from 3200px+. Type and spacing grow
|
|
76
|
+
proportionally (the design is rem-based) with no component changes. */
|
|
77
|
+
html { background: var(--background); font-size: clamp(14px, 0.35vw + 7.3px, 18px); }
|
|
72
78
|
`.replace(/\s+/g, " ").trim();
|
|
73
79
|
|
|
74
80
|
export default async function RootLayout({
|
|
@@ -187,7 +187,7 @@ export function InstanceSection() {
|
|
|
187
187
|
Running on the main dev repo. Instance upgrade features are disabled.
|
|
188
188
|
Set{" "}
|
|
189
189
|
<code className="font-mono text-[11px] px-1 py-0.5 rounded bg-muted">
|
|
190
|
-
|
|
190
|
+
RELAY_INSTANCE_MODE=true
|
|
191
191
|
</code>{" "}
|
|
192
192
|
to test.
|
|
193
193
|
</p>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import {
|
|
5
|
+
AlertTriangle,
|
|
5
6
|
ChevronDown,
|
|
6
7
|
ChevronRight,
|
|
7
8
|
Network,
|
|
@@ -286,6 +287,7 @@ function ProviderRow({
|
|
|
286
287
|
export function ProvidersAndRuntimesSection() {
|
|
287
288
|
const [data, setData] = useState<ProvidersPayload | null>(null);
|
|
288
289
|
const [loading, setLoading] = useState(true);
|
|
290
|
+
const [error, setError] = useState<string | null>(null);
|
|
289
291
|
const [anthropicOpen, setAnthropicOpen] = useState(false);
|
|
290
292
|
const [openAIOpen, setOpenAIOpen] = useState(false);
|
|
291
293
|
const [openAILoginState, setOpenAILoginState] = useState<OpenAILoginState | null>(null);
|
|
@@ -298,8 +300,20 @@ export function ProvidersAndRuntimesSection() {
|
|
|
298
300
|
if (res.ok) {
|
|
299
301
|
const json = (await res.json()) as ProvidersPayload;
|
|
300
302
|
setData(json);
|
|
303
|
+
setError(null);
|
|
301
304
|
return json;
|
|
302
305
|
}
|
|
306
|
+
// A non-OK response left the section spinning forever (issue #9): the
|
|
307
|
+
// render guard is `loading || !data`, so `data` staying null on error
|
|
308
|
+
// meant a permanent "Loading…" card with no visible failure. Surface it.
|
|
309
|
+
setError(`Failed to load provider configuration (HTTP ${res.status}).`);
|
|
310
|
+
return null;
|
|
311
|
+
} catch (err) {
|
|
312
|
+
setError(
|
|
313
|
+
err instanceof Error
|
|
314
|
+
? `Failed to load provider configuration: ${err.message}`
|
|
315
|
+
: "Failed to load provider configuration.",
|
|
316
|
+
);
|
|
303
317
|
return null;
|
|
304
318
|
} finally {
|
|
305
319
|
setLoading(false);
|
|
@@ -630,7 +644,7 @@ export function ProvidersAndRuntimesSection() {
|
|
|
630
644
|
|
|
631
645
|
// ── Render ───────────────────────────────────────────────────────
|
|
632
646
|
|
|
633
|
-
if (loading
|
|
647
|
+
if (loading) {
|
|
634
648
|
return (
|
|
635
649
|
<Card className="surface-card">
|
|
636
650
|
<CardHeader>
|
|
@@ -644,6 +658,38 @@ export function ProvidersAndRuntimesSection() {
|
|
|
644
658
|
);
|
|
645
659
|
}
|
|
646
660
|
|
|
661
|
+
// Fetch finished but produced no data (non-OK response or thrown error).
|
|
662
|
+
// Show an actionable error with a retry instead of an endless spinner —
|
|
663
|
+
// the previous `loading || !data` guard silently hung here (issue #9).
|
|
664
|
+
if (!data) {
|
|
665
|
+
return (
|
|
666
|
+
<Card className="surface-card">
|
|
667
|
+
<CardHeader>
|
|
668
|
+
<CardTitle className="flex items-center gap-2">
|
|
669
|
+
<AlertTriangle className="h-5 w-5 text-destructive" />
|
|
670
|
+
Providers & Runtimes
|
|
671
|
+
</CardTitle>
|
|
672
|
+
<CardDescription>
|
|
673
|
+
{error ?? "Failed to load provider configuration."}
|
|
674
|
+
</CardDescription>
|
|
675
|
+
</CardHeader>
|
|
676
|
+
<CardContent>
|
|
677
|
+
<button
|
|
678
|
+
type="button"
|
|
679
|
+
onClick={() => {
|
|
680
|
+
setLoading(true);
|
|
681
|
+
setError(null);
|
|
682
|
+
void fetchData();
|
|
683
|
+
}}
|
|
684
|
+
className="rounded-md border border-input bg-background px-3 py-1.5 text-sm font-medium hover:bg-accent hover:text-accent-foreground"
|
|
685
|
+
>
|
|
686
|
+
Retry
|
|
687
|
+
</button>
|
|
688
|
+
</CardContent>
|
|
689
|
+
</Card>
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
|
|
647
693
|
const { providers, routingPreference, configuredProviderCount } = data;
|
|
648
694
|
const openAIProvider: ProviderState = {
|
|
649
695
|
...providers.openai,
|