blob: 3ada71345e788bc57cef98a992b63bc43aebd81c (
plain)
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
|
import type { ResolvedModel } from "../types/index.js";
import type { ModelRegistry } from "./registry.js";
export class ModelResolver {
private registry: ModelRegistry;
constructor(registry: ModelRegistry) {
this.registry = registry;
}
resolve(tag: string): ResolvedModel | null {
const models = this.registry.getModelsByTag(tag);
const keys = this.registry.getKeys();
for (const keyState of keys) {
if (keyState.status !== "active") continue;
const model = models.find((m) => m.provider === keyState.definition.provider);
if (model) {
return { model, key: keyState.definition };
}
}
return null;
}
async waitForKey(
tag: string,
options?: {
pollIntervalMs?: number;
signal?: AbortSignal;
onWaiting?: () => void;
onResume?: () => void;
},
): Promise<ResolvedModel | null> {
const pollIntervalMs = options?.pollIntervalMs ?? 60000;
const signal = options?.signal;
// Try immediately first
const immediate = this.resolve(tag);
if (immediate) return immediate;
// Check if aborted before entering wait state
if (signal?.aborted) return null;
options?.onWaiting?.();
return new Promise<ResolvedModel | null>((resolve) => {
let timer: ReturnType<typeof setTimeout> | null = null;
const cleanup = () => {
if (timer !== null) {
clearTimeout(timer);
timer = null;
}
};
const onAbort = () => {
cleanup();
resolve(null);
};
if (signal) {
signal.addEventListener("abort", onAbort, { once: true });
}
const poll = () => {
if (signal?.aborted) {
resolve(null);
return;
}
const result = this.resolve(tag);
if (result) {
if (signal) {
signal.removeEventListener("abort", onAbort);
}
options?.onResume?.();
resolve(result);
return;
}
timer = setTimeout(poll, pollIntervalMs);
};
timer = setTimeout(poll, pollIntervalMs);
});
}
}
|