nexus-agents 2.102.7 → 2.103.0
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/{child-mcp-config-NBELOYYZ.js → child-mcp-config-IPPKT47T.js} +2 -2
- package/dist/{chunk-FRAMV5DJ.js → chunk-3TOHOAB2.js} +360 -212
- package/dist/chunk-3TOHOAB2.js.map +1 -0
- package/dist/{chunk-SBYFWB6J.js → chunk-3VSLKTD6.js} +4 -4
- package/dist/{chunk-QYE6GEPY.js → chunk-4FIY62UC.js} +3 -3
- package/dist/{chunk-FLUC27DF.js → chunk-6XWIR6JJ.js} +2 -2
- package/dist/{chunk-VJR46M7L.js → chunk-ANHBUWOI.js} +3 -3
- package/dist/{chunk-FVWKAEYH.js → chunk-AO2SCUPO.js} +2 -2
- package/dist/{chunk-FZCB2P3F.js → chunk-BUZ62ZOK.js} +2 -2
- package/dist/{chunk-4RW6OONY.js → chunk-CNQZ6BJE.js} +2 -2
- package/dist/{chunk-PWDIIS7L.js → chunk-F6X6UH6D.js} +7 -7
- package/dist/{chunk-SXWJ7IUF.js → chunk-FESEHMBN.js} +21 -2
- package/dist/{chunk-SXWJ7IUF.js.map → chunk-FESEHMBN.js.map} +1 -1
- package/dist/{chunk-6CIEBFDV.js → chunk-FPY53SSC.js} +7 -7
- package/dist/{chunk-LXBWH5XP.js → chunk-FSXN5GGJ.js} +3 -3
- package/dist/{chunk-E47LOV6Y.js → chunk-H6QEJT56.js} +2 -2
- package/dist/{chunk-4L7FH53H.js → chunk-IEFH53RH.js} +2 -2
- package/dist/{chunk-3GF52QPA.js → chunk-K4H5LCSU.js} +77 -30
- package/dist/chunk-K4H5LCSU.js.map +1 -0
- package/dist/{chunk-LVGYWJDX.js → chunk-M6QD4H7S.js} +2 -2
- package/dist/{chunk-GDY23NDK.js → chunk-NO66DOR2.js} +2 -2
- package/dist/{chunk-NAKDVIXS.js → chunk-Q5DDXJWJ.js} +3 -3
- package/dist/{chunk-KLYBJUTK.js → chunk-Q732LOXE.js} +325 -64
- package/dist/{chunk-KLYBJUTK.js.map → chunk-Q732LOXE.js.map} +1 -1
- package/dist/{chunk-ECZLYZCI.js → chunk-QA5IABQ4.js} +5 -5
- package/dist/{chunk-MNFEZIRI.js → chunk-QSTVUC2C.js} +2 -2
- package/dist/{chunk-ABGRFLJ6.js → chunk-RJ2FCK5T.js} +4 -4
- package/dist/{chunk-TDXLS2TY.js → chunk-S5LL7Y77.js} +4 -4
- package/dist/{chunk-Z7IQUUTZ.js → chunk-STLETCQJ.js} +2 -2
- package/dist/{chunk-MNWYIYEZ.js → chunk-TJVGB4OE.js} +2 -2
- package/dist/{chunk-W65C5VVJ.js → chunk-TNX3SEBY.js} +2 -2
- package/dist/{chunk-EKO6XAAZ.js → chunk-TQLSHKPJ.js} +3 -3
- package/dist/{chunk-T32MGJMA.js → chunk-TY2M7UQD.js} +10 -12
- package/dist/{chunk-T32MGJMA.js.map → chunk-TY2M7UQD.js.map} +1 -1
- package/dist/{chunk-3QFQG5QT.js → chunk-VOGIG42V.js} +2 -2
- package/dist/{chunk-5PZIMHNA.js → chunk-VU252OUC.js} +3 -3
- package/dist/{chunk-S7R72HUB.js → chunk-YMBG7LCM.js} +2 -2
- package/dist/{cli-circuit-breaker-L647V6BR.js → cli-circuit-breaker-KSNJ2KWP.js} +4 -4
- package/dist/cli.js +40 -39
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-NOTUOXFI.js → composite-router-5BO2RU4R.js} +2 -2
- package/dist/{consensus-vote-7CE4JOMK.js → consensus-vote-4W2MOXL2.js} +12 -13
- package/dist/{context-retriever-SHT7J6BT.js → context-retriever-EFEWHU3Z.js} +6 -6
- package/dist/{doctor-deep-REMLGFXP.js → doctor-deep-AWSHPMB3.js} +3 -3
- package/dist/{expert-bridge-2TYPRNEE.js → expert-bridge-P4NWKKOI.js} +4 -4
- package/dist/{factory-PPAK3TVG.js → factory-BSWATZK3.js} +5 -5
- package/dist/{factory-CYUNYEMU.js → factory-OHAMFHSF.js} +5 -5
- package/dist/{improvement-review-YFQ5T7I3.js → improvement-review-5ZWAZUB6.js} +4 -4
- package/dist/index.d.ts +15 -4
- package/dist/index.js +30 -32
- package/dist/index.js.map +1 -1
- package/dist/{init-opencode-WXY4DUFU.js → init-opencode-7O6XN2QB.js} +5 -5
- package/dist/{issue-triage-4YJQU3HW.js → issue-triage-MBNGFPVS.js} +5 -5
- package/dist/{pr-reviewer-helpers-2YJG6XJM.js → pr-reviewer-helpers-L5KOZXJO.js} +4 -4
- package/dist/{registry-command-ZFOGLBKF.js → registry-command-F565N7EI.js} +2 -2
- package/dist/{repo-security-plan-L47DDTAU.js → repo-security-plan-JRL6NQKO.js} +3 -3
- package/dist/{research-helpers-synthesize-IABO7LB4.js → research-helpers-synthesize-KJ7H75QA.js} +3 -3
- package/dist/{routing-memory-2YWEWRMQ.js → routing-memory-YECWDSDV.js} +2 -2
- package/dist/{session-memory-YWOMPCLZ.js → session-memory-AG4IM3JY.js} +3 -3
- package/dist/{setup-command-G3Q3UKI5.js → setup-command-WAUXPMOU.js} +10 -11
- package/dist/{setup-config-PYFK2GIC.js → setup-config-2GDDU5CV.js} +3 -3
- package/dist/{setup-custom-api-A4IZQ2Q4.js → setup-custom-api-6N2BTUGY.js} +4 -4
- package/dist/{tool-memory-ABPSCFIH.js → tool-memory-3ZWQVJX3.js} +5 -5
- package/dist/{weather-report-GXD6KGDS.js → weather-report-WAOVQRGI.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-3GF52QPA.js.map +0 -1
- package/dist/chunk-FRAMV5DJ.js.map +0 -1
- package/dist/chunk-L2NPJRZZ.js +0 -153
- package/dist/chunk-L2NPJRZZ.js.map +0 -1
- /package/dist/{child-mcp-config-NBELOYYZ.js.map → child-mcp-config-IPPKT47T.js.map} +0 -0
- /package/dist/{chunk-SBYFWB6J.js.map → chunk-3VSLKTD6.js.map} +0 -0
- /package/dist/{chunk-QYE6GEPY.js.map → chunk-4FIY62UC.js.map} +0 -0
- /package/dist/{chunk-FLUC27DF.js.map → chunk-6XWIR6JJ.js.map} +0 -0
- /package/dist/{chunk-VJR46M7L.js.map → chunk-ANHBUWOI.js.map} +0 -0
- /package/dist/{chunk-FVWKAEYH.js.map → chunk-AO2SCUPO.js.map} +0 -0
- /package/dist/{chunk-FZCB2P3F.js.map → chunk-BUZ62ZOK.js.map} +0 -0
- /package/dist/{chunk-4RW6OONY.js.map → chunk-CNQZ6BJE.js.map} +0 -0
- /package/dist/{chunk-PWDIIS7L.js.map → chunk-F6X6UH6D.js.map} +0 -0
- /package/dist/{chunk-6CIEBFDV.js.map → chunk-FPY53SSC.js.map} +0 -0
- /package/dist/{chunk-LXBWH5XP.js.map → chunk-FSXN5GGJ.js.map} +0 -0
- /package/dist/{chunk-E47LOV6Y.js.map → chunk-H6QEJT56.js.map} +0 -0
- /package/dist/{chunk-4L7FH53H.js.map → chunk-IEFH53RH.js.map} +0 -0
- /package/dist/{chunk-LVGYWJDX.js.map → chunk-M6QD4H7S.js.map} +0 -0
- /package/dist/{chunk-GDY23NDK.js.map → chunk-NO66DOR2.js.map} +0 -0
- /package/dist/{chunk-NAKDVIXS.js.map → chunk-Q5DDXJWJ.js.map} +0 -0
- /package/dist/{chunk-ECZLYZCI.js.map → chunk-QA5IABQ4.js.map} +0 -0
- /package/dist/{chunk-MNFEZIRI.js.map → chunk-QSTVUC2C.js.map} +0 -0
- /package/dist/{chunk-ABGRFLJ6.js.map → chunk-RJ2FCK5T.js.map} +0 -0
- /package/dist/{chunk-TDXLS2TY.js.map → chunk-S5LL7Y77.js.map} +0 -0
- /package/dist/{chunk-Z7IQUUTZ.js.map → chunk-STLETCQJ.js.map} +0 -0
- /package/dist/{chunk-MNWYIYEZ.js.map → chunk-TJVGB4OE.js.map} +0 -0
- /package/dist/{chunk-W65C5VVJ.js.map → chunk-TNX3SEBY.js.map} +0 -0
- /package/dist/{chunk-EKO6XAAZ.js.map → chunk-TQLSHKPJ.js.map} +0 -0
- /package/dist/{chunk-3QFQG5QT.js.map → chunk-VOGIG42V.js.map} +0 -0
- /package/dist/{chunk-5PZIMHNA.js.map → chunk-VU252OUC.js.map} +0 -0
- /package/dist/{chunk-S7R72HUB.js.map → chunk-YMBG7LCM.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-L647V6BR.js.map → cli-circuit-breaker-KSNJ2KWP.js.map} +0 -0
- /package/dist/{composite-router-NOTUOXFI.js.map → composite-router-5BO2RU4R.js.map} +0 -0
- /package/dist/{consensus-vote-7CE4JOMK.js.map → consensus-vote-4W2MOXL2.js.map} +0 -0
- /package/dist/{context-retriever-SHT7J6BT.js.map → context-retriever-EFEWHU3Z.js.map} +0 -0
- /package/dist/{doctor-deep-REMLGFXP.js.map → doctor-deep-AWSHPMB3.js.map} +0 -0
- /package/dist/{expert-bridge-2TYPRNEE.js.map → expert-bridge-P4NWKKOI.js.map} +0 -0
- /package/dist/{factory-CYUNYEMU.js.map → factory-BSWATZK3.js.map} +0 -0
- /package/dist/{factory-PPAK3TVG.js.map → factory-OHAMFHSF.js.map} +0 -0
- /package/dist/{improvement-review-YFQ5T7I3.js.map → improvement-review-5ZWAZUB6.js.map} +0 -0
- /package/dist/{init-opencode-WXY4DUFU.js.map → init-opencode-7O6XN2QB.js.map} +0 -0
- /package/dist/{issue-triage-4YJQU3HW.js.map → issue-triage-MBNGFPVS.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-2YJG6XJM.js.map → pr-reviewer-helpers-L5KOZXJO.js.map} +0 -0
- /package/dist/{registry-command-ZFOGLBKF.js.map → registry-command-F565N7EI.js.map} +0 -0
- /package/dist/{repo-security-plan-L47DDTAU.js.map → repo-security-plan-JRL6NQKO.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-IABO7LB4.js.map → research-helpers-synthesize-KJ7H75QA.js.map} +0 -0
- /package/dist/{routing-memory-2YWEWRMQ.js.map → routing-memory-YECWDSDV.js.map} +0 -0
- /package/dist/{session-memory-YWOMPCLZ.js.map → session-memory-AG4IM3JY.js.map} +0 -0
- /package/dist/{setup-command-G3Q3UKI5.js.map → setup-command-WAUXPMOU.js.map} +0 -0
- /package/dist/{setup-config-PYFK2GIC.js.map → setup-config-2GDDU5CV.js.map} +0 -0
- /package/dist/{setup-custom-api-A4IZQ2Q4.js.map → setup-custom-api-6N2BTUGY.js.map} +0 -0
- /package/dist/{tool-memory-ABPSCFIH.js.map → tool-memory-3ZWQVJX3.js.map} +0 -0
- /package/dist/{weather-report-GXD6KGDS.js.map → weather-report-WAOVQRGI.js.map} +0 -0
package/dist/chunk-L2NPJRZZ.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createLogger
|
|
3
|
-
} from "./chunk-KLYBJUTK.js";
|
|
4
|
-
|
|
5
|
-
// src/config/available-models-cache.ts
|
|
6
|
-
var logger = createLogger({ component: "available-models-cache" });
|
|
7
|
-
var DEFAULT_TTL_MS = 5 * 60 * 1e3;
|
|
8
|
-
var DEFAULT_STALE_TTL_MS = 25 * 60 * 1e3;
|
|
9
|
-
var AvailableModelsCache = class {
|
|
10
|
-
sources;
|
|
11
|
-
ttlMs;
|
|
12
|
-
staleTtlMs;
|
|
13
|
-
now;
|
|
14
|
-
states;
|
|
15
|
-
constructor(options) {
|
|
16
|
-
this.sources = [...options.sources];
|
|
17
|
-
this.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
18
|
-
this.staleTtlMs = options.staleTtlMs ?? DEFAULT_STALE_TTL_MS;
|
|
19
|
-
this.now = options.now ?? Date.now;
|
|
20
|
-
this.states = /* @__PURE__ */ new Map();
|
|
21
|
-
for (const s of this.sources) {
|
|
22
|
-
this.states.set(s.name, { value: null, fetchedAt: 0, inFlight: null });
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Register a source after construction. Used by adapter factories that
|
|
27
|
-
* wire themselves into the default cache lazily as they're built.
|
|
28
|
-
* Duplicate names are ignored (first registration wins, on the
|
|
29
|
-
* assumption that the same factory might run twice in a test session).
|
|
30
|
-
*/
|
|
31
|
-
addSource(source) {
|
|
32
|
-
if (this.states.has(source.name)) return;
|
|
33
|
-
this.sources.push(source);
|
|
34
|
-
this.states.set(source.name, { value: null, fetchedAt: 0, inFlight: null });
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Remove a previously-registered source. Used by tests + by factories
|
|
38
|
-
* that want to drop a probe when an adapter is being disposed.
|
|
39
|
-
*/
|
|
40
|
-
removeSource(name) {
|
|
41
|
-
this.sources = this.sources.filter((s) => s.name !== name);
|
|
42
|
-
this.states.delete(name);
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Returns the union of every source's available models. Stale-while-
|
|
46
|
-
* revalidate: serve fresh-or-stale immediately, refresh stale entries
|
|
47
|
-
* in the background. First call (no cache yet) blocks on every source.
|
|
48
|
-
*/
|
|
49
|
-
async getAll() {
|
|
50
|
-
const probes = this.sources.map((s) => this.probeOne(s));
|
|
51
|
-
const results = await Promise.all(probes);
|
|
52
|
-
const out = [];
|
|
53
|
-
for (const r of results) {
|
|
54
|
-
for (const m of r) out.push(m);
|
|
55
|
-
}
|
|
56
|
-
return out;
|
|
57
|
-
}
|
|
58
|
-
/** Models reported by one named source (subset of getAll). */
|
|
59
|
-
async byProvider(sourceName) {
|
|
60
|
-
const all = await this.getAll();
|
|
61
|
-
return all.filter((m) => m.source === sourceName);
|
|
62
|
-
}
|
|
63
|
-
/** True iff some source currently reports the given model id. */
|
|
64
|
-
async has(modelId) {
|
|
65
|
-
const all = await this.getAll();
|
|
66
|
-
return all.some((m) => m.id === modelId);
|
|
67
|
-
}
|
|
68
|
-
/** Force a synchronous refresh of every source — used after a 404. */
|
|
69
|
-
async refresh() {
|
|
70
|
-
for (const s of this.sources) {
|
|
71
|
-
const state = this.states.get(s.name);
|
|
72
|
-
if (state === void 0) continue;
|
|
73
|
-
state.fetchedAt = 0;
|
|
74
|
-
state.value = null;
|
|
75
|
-
}
|
|
76
|
-
return this.getAll();
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Probe one source. Returns:
|
|
80
|
-
* - cached value if still fresh
|
|
81
|
-
* - cached value AND kicks a background refresh if stale-but-not-expired
|
|
82
|
-
* - blocks on the source if no cache or fully expired
|
|
83
|
-
*
|
|
84
|
-
* Source errors yield an empty list (logged) so one bad source can't
|
|
85
|
-
* poison the union.
|
|
86
|
-
*/
|
|
87
|
-
async probeOne(source) {
|
|
88
|
-
const state = this.getState(source.name);
|
|
89
|
-
const age = this.now() - state.fetchedAt;
|
|
90
|
-
if (state.value !== null && age < this.ttlMs) {
|
|
91
|
-
return state.value;
|
|
92
|
-
}
|
|
93
|
-
if (state.value !== null && age < this.staleTtlMs) {
|
|
94
|
-
state.inFlight ??= this.fetchSource(source).finally(() => {
|
|
95
|
-
state.inFlight = null;
|
|
96
|
-
});
|
|
97
|
-
return state.value;
|
|
98
|
-
}
|
|
99
|
-
if (state.inFlight !== null) return state.inFlight;
|
|
100
|
-
state.inFlight = this.fetchSource(source).finally(() => {
|
|
101
|
-
state.inFlight = null;
|
|
102
|
-
});
|
|
103
|
-
return state.inFlight;
|
|
104
|
-
}
|
|
105
|
-
async fetchSource(source) {
|
|
106
|
-
const state = this.getState(source.name);
|
|
107
|
-
try {
|
|
108
|
-
const raw = await source.listModels();
|
|
109
|
-
const value = raw.map((m) => normaliseEntry(m, source));
|
|
110
|
-
state.value = value;
|
|
111
|
-
state.fetchedAt = this.now();
|
|
112
|
-
return value;
|
|
113
|
-
} catch (e) {
|
|
114
|
-
logger.warn("AvailableModelsCache source probe failed", {
|
|
115
|
-
source: source.name,
|
|
116
|
-
error: e instanceof Error ? e.message : String(e)
|
|
117
|
-
});
|
|
118
|
-
return state.value ?? [];
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
getState(name) {
|
|
122
|
-
const state = this.states.get(name);
|
|
123
|
-
if (state === void 0) {
|
|
124
|
-
throw new Error(`AvailableModelsCache: unknown source "${name}"`);
|
|
125
|
-
}
|
|
126
|
-
return state;
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
function normaliseEntry(raw, source) {
|
|
130
|
-
const slash = raw.id.indexOf("/");
|
|
131
|
-
if (slash > 0 && slash < raw.id.length - 1) {
|
|
132
|
-
return { id: raw.id, source: source.name, provider: raw.id.slice(0, slash) };
|
|
133
|
-
}
|
|
134
|
-
if (source.providerHint !== void 0) {
|
|
135
|
-
return { id: raw.id, source: source.name, provider: source.providerHint };
|
|
136
|
-
}
|
|
137
|
-
return { id: raw.id, source: source.name };
|
|
138
|
-
}
|
|
139
|
-
var defaultCache = null;
|
|
140
|
-
function getDefaultAvailableModelsCache() {
|
|
141
|
-
defaultCache ??= new AvailableModelsCache({ sources: [] });
|
|
142
|
-
return defaultCache;
|
|
143
|
-
}
|
|
144
|
-
function setDefaultAvailableModelsCache(cache) {
|
|
145
|
-
defaultCache = cache;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export {
|
|
149
|
-
AvailableModelsCache,
|
|
150
|
-
getDefaultAvailableModelsCache,
|
|
151
|
-
setDefaultAvailableModelsCache
|
|
152
|
-
};
|
|
153
|
-
//# sourceMappingURL=chunk-L2NPJRZZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/available-models-cache.ts"],"sourcesContent":["/**\n * AvailableModelsCache (#2540 PR 6 of 8).\n *\n * Central, harness-driven view of what models the runtime can actually\n * dispatch to right now. PR 5 added `listModels()` on direct-API adapters\n * (Anthropic, Google, OpenAI gateway) and on the OpenCode CLI adapter;\n * this cache stitches those probes together into one queryable surface.\n *\n * Design invariants:\n *\n * 1. Sources are the source of truth — if a harness drops a model,\n * the registry never decides it's still routable. The\n * `ModelRegistry` (PR 1) answers \"how should this model behave\"\n * while this cache answers \"is this model routable at all\".\n *\n * 2. Stale-while-revalidate: serve the most recent successful result\n * while a refresh runs in the background, so callers never block on\n * a slow `models.list` round-trip.\n *\n * 3. One bad source must not poison the others. A failing `listModels`\n * logs and is excluded from the next snapshot; remaining sources\n * remain queryable.\n *\n * 4. No persistence. Process-local cache only — operators restart and\n * get a fresh probe. Persistence belongs in PR 7 if it's needed.\n */\n\nimport { createLogger } from '../core/logger.js';\n\nconst logger = createLogger({ component: 'available-models-cache' });\n\n/** Default freshness TTL: 5 minutes — matches per-adapter listModels TTL. */\nconst DEFAULT_TTL_MS = 5 * 60 * 1000;\n/** Default stale TTL: 25 minutes — beyond this, callers wait on a refresh. */\nconst DEFAULT_STALE_TTL_MS = 25 * 60 * 1000;\n\n/**\n * One adapter (CLI or API) that can be asked what models it currently has.\n * Exists so this cache doesn't have to know about IModelAdapter vs\n * ICliAdapter — both can adapt themselves to this minimal surface.\n */\nexport interface AvailableModelsSource {\n /** Stable, human-readable identifier — e.g. `claude`, `gateway-openrouter`. */\n readonly name: string;\n /**\n * Optional vendor-family hint — `anthropic` / `openai` / `google` / etc.\n * Used to pre-tag entries when the source's own model ids don't carry\n * a `provider/` prefix (Anthropic API, Google API).\n */\n readonly providerHint?: string;\n /** Probe the underlying surface for currently available models. */\n listModels(): Promise<readonly { id: string }[]>;\n}\n\n/** One row in the cache: model id + which source first reported it. */\nexport interface AvailableModel {\n readonly id: string;\n readonly source: string;\n /** `provider/` prefix when the source uses one; otherwise the providerHint. */\n readonly provider?: string;\n}\n\nexport interface AvailableModelsCacheOptions {\n readonly sources: readonly AvailableModelsSource[];\n /** Freshness TTL (ms). Defaults to 5 minutes. */\n readonly ttlMs?: number;\n /** Beyond this, callers block on the next refresh. Defaults to 25 minutes. */\n readonly staleTtlMs?: number;\n /** Override `Date.now` for tests. */\n readonly now?: () => number;\n}\n\ninterface SourceState {\n value: readonly AvailableModel[] | null;\n fetchedAt: number;\n inFlight: Promise<readonly AvailableModel[]> | null;\n}\n\nexport class AvailableModelsCache {\n private sources: AvailableModelsSource[];\n private readonly ttlMs: number;\n private readonly staleTtlMs: number;\n private readonly now: () => number;\n private readonly states: Map<string, SourceState>;\n\n constructor(options: AvailableModelsCacheOptions) {\n this.sources = [...options.sources];\n this.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;\n this.staleTtlMs = options.staleTtlMs ?? DEFAULT_STALE_TTL_MS;\n this.now = options.now ?? Date.now;\n this.states = new Map();\n for (const s of this.sources) {\n this.states.set(s.name, { value: null, fetchedAt: 0, inFlight: null });\n }\n }\n\n /**\n * Register a source after construction. Used by adapter factories that\n * wire themselves into the default cache lazily as they're built.\n * Duplicate names are ignored (first registration wins, on the\n * assumption that the same factory might run twice in a test session).\n */\n addSource(source: AvailableModelsSource): void {\n if (this.states.has(source.name)) return;\n this.sources.push(source);\n this.states.set(source.name, { value: null, fetchedAt: 0, inFlight: null });\n }\n\n /**\n * Remove a previously-registered source. Used by tests + by factories\n * that want to drop a probe when an adapter is being disposed.\n */\n removeSource(name: string): void {\n this.sources = this.sources.filter((s) => s.name !== name);\n this.states.delete(name);\n }\n\n /**\n * Returns the union of every source's available models. Stale-while-\n * revalidate: serve fresh-or-stale immediately, refresh stale entries\n * in the background. First call (no cache yet) blocks on every source.\n */\n async getAll(): Promise<readonly AvailableModel[]> {\n const probes = this.sources.map((s) => this.probeOne(s));\n const results = await Promise.all(probes);\n const out: AvailableModel[] = [];\n for (const r of results) {\n for (const m of r) out.push(m);\n }\n return out;\n }\n\n /** Models reported by one named source (subset of getAll). */\n async byProvider(sourceName: string): Promise<readonly AvailableModel[]> {\n const all = await this.getAll();\n return all.filter((m) => m.source === sourceName);\n }\n\n /** True iff some source currently reports the given model id. */\n async has(modelId: string): Promise<boolean> {\n const all = await this.getAll();\n return all.some((m) => m.id === modelId);\n }\n\n /** Force a synchronous refresh of every source — used after a 404. */\n async refresh(): Promise<readonly AvailableModel[]> {\n for (const s of this.sources) {\n const state = this.states.get(s.name);\n if (state === undefined) continue;\n state.fetchedAt = 0;\n state.value = null;\n }\n return this.getAll();\n }\n\n /**\n * Probe one source. Returns:\n * - cached value if still fresh\n * - cached value AND kicks a background refresh if stale-but-not-expired\n * - blocks on the source if no cache or fully expired\n *\n * Source errors yield an empty list (logged) so one bad source can't\n * poison the union.\n */\n private async probeOne(source: AvailableModelsSource): Promise<readonly AvailableModel[]> {\n const state = this.getState(source.name);\n const age = this.now() - state.fetchedAt;\n\n if (state.value !== null && age < this.ttlMs) {\n return state.value;\n }\n if (state.value !== null && age < this.staleTtlMs) {\n state.inFlight ??= this.fetchSource(source).finally(() => {\n state.inFlight = null;\n });\n return state.value;\n }\n if (state.inFlight !== null) return state.inFlight;\n state.inFlight = this.fetchSource(source).finally(() => {\n state.inFlight = null;\n });\n return state.inFlight;\n }\n\n private async fetchSource(source: AvailableModelsSource): Promise<readonly AvailableModel[]> {\n const state = this.getState(source.name);\n try {\n const raw = await source.listModels();\n const value = raw.map((m) => normaliseEntry(m, source));\n state.value = value;\n state.fetchedAt = this.now();\n return value;\n } catch (e: unknown) {\n logger.warn('AvailableModelsCache source probe failed', {\n source: source.name,\n error: e instanceof Error ? e.message : String(e),\n });\n // Keep the stale value if we have one; otherwise empty.\n return state.value ?? [];\n }\n }\n\n private getState(name: string): SourceState {\n const state = this.states.get(name);\n // Constructor seeds an entry for every configured source, and the public\n // surface only routes through `this.sources`, so a missing state would\n // be a programming error — surface it loudly rather than masking it.\n if (state === undefined) {\n throw new Error(`AvailableModelsCache: unknown source \"${name}\"`);\n }\n return state;\n }\n}\n\nfunction normaliseEntry(raw: { id: string }, source: AvailableModelsSource): AvailableModel {\n const slash = raw.id.indexOf('/');\n if (slash > 0 && slash < raw.id.length - 1) {\n return { id: raw.id, source: source.name, provider: raw.id.slice(0, slash) };\n }\n if (source.providerHint !== undefined) {\n return { id: raw.id, source: source.name, provider: source.providerHint };\n }\n return { id: raw.id, source: source.name };\n}\n\n// ============================================================================\n// Default (process-singleton) instance — used by adapter factories that\n// auto-wire `withModelNotFoundFallback`. Operators that need a different\n// cache (different TTLs, custom sources) can override via\n// `setDefaultAvailableModelsCache` at startup.\n// ============================================================================\n\nlet defaultCache: AvailableModelsCache | null = null;\n\n/**\n * Get (or lazily construct) the process-default cache. Starts with no\n * sources — adapter factories register themselves via `addSource` on\n * construction. Until at least one source is added, the cache returns\n * empty snapshots and `withModelNotFoundFallback` degrades to surfacing\n * the original error (safe).\n */\nexport function getDefaultAvailableModelsCache(): AvailableModelsCache {\n defaultCache ??= new AvailableModelsCache({ sources: [] });\n return defaultCache;\n}\n\n/**\n * Override the default cache. Useful for tests and for operators that\n * want a pre-populated cache wired at startup.\n */\nexport function setDefaultAvailableModelsCache(cache: AvailableModelsCache | null): void {\n defaultCache = cache;\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|