mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-19 05:09:30 +02:00
fix: portail laissant passer /health mais bloquant /v1 traité comme liaison en échec (v2.4.0.3) (#18)
- Une page web reçue sur /v1/capabilities fait échouer la connexion et le test de liaison même si /health répond, ce qui déclenche la recherche de l'API. - La découverte sonde /v1/capabilities puis /v1/models (JSON exigé, 401/403 accepté) avant /health, pour ne pas prendre un portail pour l'API. Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
df25dd591c
commit
d1b12c16c5
5 files changed
+26
-10
No files matched your search
@@ -108,6 +108,7 @@ export function SettingsDrawer({ onClose }: Props) {
|
||||
caps = ` · modèle ${String(c.model ?? '?')} · ${Object.entries(c.features ?? {}).filter(([, v]) => v === true).length} fonctions`;
|
||||
} catch (err) {
|
||||
const message = (err as Error).message;
|
||||
if (/page web/.test(message)) throw err;
|
||||
caps = /404/.test(message)
|
||||
? ' · /v1/capabilities absent (Hermes ancien : transport chat completions)'
|
||||
: ` · capabilities : ${message}`;
|
||||
|
||||
@@ -72,18 +72,30 @@ export function hermesUrlCandidates(url: string): string[] {
|
||||
return [...out];
|
||||
}
|
||||
|
||||
/** Probe candidate URLs until one answers Hermes JSON on /health or /v1/capabilities. */
|
||||
/** True when this base URL answers like the Hermes API (JSON on /v1/*, or 401/403 = key required). */
|
||||
export async function probeHermesUrl(config: HermesConfig, url: string): Promise<boolean> {
|
||||
const client = new HermesClient({ ...config, url });
|
||||
for (const path of ['/v1/capabilities', '/v1/models', '/health']) {
|
||||
try {
|
||||
const payload = await client.request<unknown>(path, { timeoutMs: 4000 });
|
||||
if (payload && typeof payload === 'object') return true;
|
||||
} catch (err) {
|
||||
if (err instanceof HttpError) {
|
||||
if (err.status === 401 || err.status === 403) return true; // the API is there, only the key is missing
|
||||
if (/page web/.test(err.message)) return false; // a portal answers on this host: not the API
|
||||
if (err.status === 404) continue; // older Hermes without this endpoint
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Probe candidate URLs until one answers like the Hermes API. */
|
||||
export async function discoverHermesUrl(config: HermesConfig, onProgress?: (url: string) => void): Promise<string | null> {
|
||||
for (const candidate of hermesUrlCandidates(config.url)) {
|
||||
onProgress?.(candidate);
|
||||
const client = new HermesClient({ ...config, url: candidate });
|
||||
try {
|
||||
await client.request<unknown>('/health', { timeoutMs: 4000 });
|
||||
return candidate;
|
||||
} catch (err) {
|
||||
if (err instanceof HttpError && (err.status === 401 || err.status === 403)) return candidate; // API found, key missing
|
||||
continue;
|
||||
}
|
||||
if (await probeHermesUrl(config, candidate)) return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,8 @@ export const useHermes = create<HermesStore>((set, get) => ({
|
||||
try {
|
||||
capabilities = await client.capabilities();
|
||||
} catch (err) {
|
||||
// A web page on /v1/* means the whole API is behind a portal even if /health passed through.
|
||||
if (/page web/.test((err as Error).message)) throw err;
|
||||
Log.warn('hermes', `capabilities unavailable: ${(err as Error).message}`);
|
||||
}
|
||||
const transport = resolveTransport(config, capabilities);
|
||||
|
||||
Reference in new issue
Block a user