File size: 1,959 Bytes
0b9dc2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useEffect, useState } from 'react';

import { knowledgeBaseApi } from '@/api';
import type { JSONSchema } from '@/api';

/**

 * Module-level cache for the KB middleware parameter schema.

 *

 * The schema is class-static on the backend (derived from

 * :class:`KnowledgeBaseMiddleware.Parameters.model_json_schema()`),

 * so a single fetch per page load is enough.  Several mounted

 * `KnowledgeBasePanel`s would otherwise each fire the request — the

 * cache de-duplicates concurrent callers, too.

 */
let cached: JSONSchema | null = null;
let inflight: Promise<JSONSchema> | null = null;

async function fetchSchema(): Promise<JSONSchema> {
	if (cached) return cached;
	if (inflight) return inflight;
	inflight = knowledgeBaseApi
		.middlewareParametersSchema()
		.then((res) => {
			cached = res.parameter_schema as unknown as JSONSchema;
			return cached;
		})
		.finally(() => {
			inflight = null;
		});
	return inflight;
}

/**

 * Fetch the parameter schema for the session-level

 * `KnowledgeBaseMiddleware`.

 *

 * Returns the schema once available; `null` while loading. The schema

 * is shared across all callers via a module-level cache.

 */
export function useKnowledgeBaseMiddlewareSchema(): {
	schema: JSONSchema | null;
	loading: boolean;
	error: Error | null;
} {
	const [schema, setSchema] = useState<JSONSchema | null>(cached);
	const [loading, setLoading] = useState(cached === null);
	const [error, setError] = useState<Error | null>(null);

	useEffect(() => {
		if (cached) {
			setSchema(cached);
			return;
		}
		let cancelled = false;
		setLoading(true);
		fetchSchema()
			.then((s) => {
				if (!cancelled) setSchema(s);
			})
			.catch((e) => {
				if (!cancelled) setError(e as Error);
			})
			.finally(() => {
				if (!cancelled) setLoading(false);
			});
		return () => {
			cancelled = true;
		};
	}, []);

	return { schema, loading, error };
}