@mcowger/opencode-plexus 1.3.8 → 1.3.10
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/README.md +42 -0
- package/dist/index.js +129 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -244,6 +244,47 @@ Both adapters also accept pi-style environment interpolation in configured strin
|
|
|
244
244
|
|
|
245
245
|
---
|
|
246
246
|
|
|
247
|
+
## Model suppression
|
|
248
|
+
|
|
249
|
+
All plugin packages support suppressing models by name or pattern so undesired models do not appear in model selectors or cache restored lists.
|
|
250
|
+
|
|
251
|
+
### Pattern matching syntax
|
|
252
|
+
|
|
253
|
+
- **Exact match** (case-insensitive): Matches model `id`, `name`, or short ID (suffix after `/` or `:`). Example: `"gpt-4o"`, `"Claude 3.5 Sonnet"`.
|
|
254
|
+
- **Glob wildcards**: Supports `*` (0+ characters) and `?` (1 character). Example: `"gpt-3.5*"`, `"*deprecated*"`, `"anthropic/*"`.
|
|
255
|
+
- **Regex patterns**: Prefix with `regex:`. Example: `"regex:^gpt-[34]"`.
|
|
256
|
+
|
|
257
|
+
### Configuration methods
|
|
258
|
+
|
|
259
|
+
- **Environment variables**:
|
|
260
|
+
```sh
|
|
261
|
+
export PLEXUS_SUPPRESS_MODELS="gpt-3.5*, *deprecated*, whisper"
|
|
262
|
+
```
|
|
263
|
+
`PLEXUS_EXCLUDE_MODELS` is also accepted. Values can be comma-, semicolon-, or newline-separated.
|
|
264
|
+
|
|
265
|
+
- **pi / Oh My Pi config**: Add `suppressModels` (or `suppress`) to `config.json`:
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"baseUrl": "https://plexus.example.com",
|
|
269
|
+
"suppressModels": ["gpt-3.5*", "*deprecated*"]
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
- **OpenCode config**: Add `suppressModels` (or `suppress`) under `provider.plexus.options` in `opencode.json`:
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"provider": {
|
|
277
|
+
"plexus": {
|
|
278
|
+
"options": {
|
|
279
|
+
"suppressModels": ["gpt-3.5*", "claude-2*"]
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
247
288
|
## Package layout
|
|
248
289
|
|
|
249
290
|
```
|
|
@@ -252,6 +293,7 @@ packages/
|
|
|
252
293
|
src/
|
|
253
294
|
types.ts # wire types (PlexusApiModel, PlexusModelDescriptor, etc.)
|
|
254
295
|
convert.ts # model fetching, conversion, compat detection
|
|
296
|
+
suppress.ts # model pattern suppression / exclusion matching
|
|
255
297
|
index.ts # barrel export
|
|
256
298
|
plexus-pi/ # pi host adapter
|
|
257
299
|
src/
|
package/dist/index.js
CHANGED
|
@@ -9,12 +9,66 @@ var PLEXUS_BASE_URL_OPTION = "plexusBaseURL";
|
|
|
9
9
|
var ENV_BASE_URL = "PLEXUS_BASE_URL";
|
|
10
10
|
var ENV_API_URL = "PLEXUS_API_URL";
|
|
11
11
|
var ENV_API_KEY = "PLEXUS_API_KEY";
|
|
12
|
+
var ENV_SUPPRESS_MODELS = "PLEXUS_SUPPRESS_MODELS";
|
|
13
|
+
var ENV_SUPPRESSED_MODELS = "PLEXUS_SUPPRESSED_MODELS";
|
|
14
|
+
var ENV_EXCLUDE_MODELS = "PLEXUS_EXCLUDE_MODELS";
|
|
15
|
+
var ENV_IGNORE_MODELS = "PLEXUS_IGNORE_MODELS";
|
|
16
|
+
var PLEXUS_SUPPRESS_MODELS_OPTION = "suppressModels";
|
|
12
17
|
var MODELS_FETCH_TIMEOUT_MS = 1e4;
|
|
13
18
|
var REFRESH_TTL_MS = 60000;
|
|
14
19
|
var CONFIG_HOOK_REFRESH_BUDGET_MS = 3000;
|
|
15
20
|
var PLACEHOLDER_MODEL_ID = "plexus-unconfigured";
|
|
16
21
|
var PLEXUS_REFRESH_COMMAND = "plexus-refresh";
|
|
17
22
|
|
|
23
|
+
// ../plexus-models/src/suppress.ts
|
|
24
|
+
function parseSuppressionPatterns(raw) {
|
|
25
|
+
if (!raw)
|
|
26
|
+
return [];
|
|
27
|
+
const items = Array.isArray(raw) ? raw : raw.split(/[\n,;]+/);
|
|
28
|
+
return items.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
29
|
+
}
|
|
30
|
+
function getEnvSuppressedModels() {
|
|
31
|
+
const env = typeof process !== "undefined" && process?.env ? process.env : {};
|
|
32
|
+
const raw = env.PLEXUS_SUPPRESS_MODELS ?? env.PLEXUS_EXCLUDE_MODELS;
|
|
33
|
+
return parseSuppressionPatterns(raw);
|
|
34
|
+
}
|
|
35
|
+
function isModelSuppressed(model, patterns) {
|
|
36
|
+
const envPatterns = getEnvSuppressedModels();
|
|
37
|
+
const explicitPatterns = parseSuppressionPatterns(patterns);
|
|
38
|
+
const allPatterns = [...envPatterns, ...explicitPatterns];
|
|
39
|
+
if (allPatterns.length === 0)
|
|
40
|
+
return false;
|
|
41
|
+
const id = model.id.toLowerCase();
|
|
42
|
+
const name = (model.name ?? "").toLowerCase();
|
|
43
|
+
const shortId = id.includes("/") ? id.split("/").pop() : id.includes(":") ? id.split(":").pop() : id;
|
|
44
|
+
for (const pattern of allPatterns) {
|
|
45
|
+
if (matchesPattern(id, name, shortId, pattern)) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
function matchesPattern(id, name, shortId, pattern) {
|
|
52
|
+
const p = pattern.toLowerCase();
|
|
53
|
+
if (p.startsWith("regex:")) {
|
|
54
|
+
try {
|
|
55
|
+
const re = new RegExp(pattern.slice(6), "i");
|
|
56
|
+
return re.test(id) || re.test(name) || re.test(shortId);
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (p.includes("*") || p.includes("?")) {
|
|
62
|
+
const regexStr = "^" + p.replace(/([.+^${}()|[\]\\])/g, "\\$1").replace(/\*/g, ".*").replace(/\?/g, ".") + "$";
|
|
63
|
+
try {
|
|
64
|
+
const re = new RegExp(regexStr, "i");
|
|
65
|
+
return re.test(id) || re.test(name) || re.test(shortId);
|
|
66
|
+
} catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return id === p || name === p || shortId === p;
|
|
71
|
+
}
|
|
18
72
|
// ../plexus-models/src/convert.ts
|
|
19
73
|
var REASONING_PARAMS = new Set(["reasoning", "include_reasoning", "reasoning_effort"]);
|
|
20
74
|
var NON_CHAT_PATTERN = /(?:^|[\W_])(?:embed(?:ding|dings)?|transcri(?:be[ds]?|ptions?)|whisper|speech[\W_]*to[\W_]*text|stt|text[\W_]*to[\W_]*speech|tts|image[\W_]*(?:gen(?:eration)?|\d+)|diffusion|dall[\W_]*e|stable[\W_]*diffusion|sdxl|dream)(?:$|[\W_])/i;
|
|
@@ -66,22 +120,28 @@ function isChatModel(model) {
|
|
|
66
120
|
return !NON_CHAT_PATTERN.test(`${model.id} ${model.name ?? ""} ${apiHints}`);
|
|
67
121
|
}
|
|
68
122
|
var DEFAULT_MODELS_FETCH_TIMEOUT_MS = 1e4;
|
|
69
|
-
async function fetchPlexusModels(apiKey, modelsUrl, timeoutMs = DEFAULT_MODELS_FETCH_TIMEOUT_MS) {
|
|
123
|
+
async function fetchPlexusModels(apiKey, modelsUrl, timeoutMs = DEFAULT_MODELS_FETCH_TIMEOUT_MS, etag) {
|
|
70
124
|
const controller = new AbortController;
|
|
71
125
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
72
126
|
try {
|
|
73
127
|
const headers = { Accept: "application/json" };
|
|
74
128
|
if (apiKey)
|
|
75
129
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
130
|
+
if (etag)
|
|
131
|
+
headers["If-None-Match"] = etag;
|
|
76
132
|
const res = await fetch(modelsUrl, {
|
|
77
133
|
headers,
|
|
78
134
|
signal: controller.signal
|
|
79
135
|
});
|
|
136
|
+
if (res.status === 304) {
|
|
137
|
+
return { models: [], notModified: true };
|
|
138
|
+
}
|
|
80
139
|
if (!res.ok) {
|
|
81
140
|
throw new Error(`Plexus models fetch failed: ${res.status} ${res.statusText}`);
|
|
82
141
|
}
|
|
83
142
|
const raw = await res.json();
|
|
84
|
-
|
|
143
|
+
const responseEtag = res.headers.get("etag") ?? undefined;
|
|
144
|
+
return { models: raw.data ?? [], raw, etag: responseEtag };
|
|
85
145
|
} catch (err) {
|
|
86
146
|
if (err instanceof Error && err.name === "AbortError") {
|
|
87
147
|
throw new Error(`Plexus models fetch timed out after ${timeoutMs}ms`);
|
|
@@ -104,34 +164,41 @@ function fallbackDir() {
|
|
|
104
164
|
function getDir() {
|
|
105
165
|
return fallbackDir();
|
|
106
166
|
}
|
|
107
|
-
function filterCachedModels(models) {
|
|
108
|
-
return Object.fromEntries(Object.entries(models).filter(([, model]) =>
|
|
109
|
-
id: model.id,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
167
|
+
function filterCachedModels(models, suppress) {
|
|
168
|
+
return Object.fromEntries(Object.entries(models).filter(([, model]) => {
|
|
169
|
+
if (isModelSuppressed({ id: model.id, name: model.name }, suppress))
|
|
170
|
+
return false;
|
|
171
|
+
return isChatModel({
|
|
172
|
+
id: model.id,
|
|
173
|
+
name: model.name,
|
|
174
|
+
architecture: {
|
|
175
|
+
input_modalities: model.modalities.input,
|
|
176
|
+
output_modalities: model.modalities.output
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}));
|
|
116
180
|
}
|
|
117
|
-
async function readCachedModels(_client) {
|
|
181
|
+
async function readCachedModels(_client, suppress) {
|
|
118
182
|
try {
|
|
119
183
|
const dir = getDir();
|
|
120
184
|
const content = await readFile(join(dir, CACHE_FILE), "utf8");
|
|
121
185
|
const parsed = JSON.parse(content);
|
|
122
186
|
if (parsed && typeof parsed.models === "object" && !Array.isArray(parsed.models)) {
|
|
123
|
-
return
|
|
187
|
+
return {
|
|
188
|
+
models: filterCachedModels(parsed.models, suppress),
|
|
189
|
+
etag: typeof parsed.etag === "string" ? parsed.etag : undefined
|
|
190
|
+
};
|
|
124
191
|
}
|
|
125
192
|
return null;
|
|
126
193
|
} catch {
|
|
127
194
|
return null;
|
|
128
195
|
}
|
|
129
196
|
}
|
|
130
|
-
async function writeCache(_client, models, raw) {
|
|
197
|
+
async function writeCache(_client, models, raw, etag) {
|
|
131
198
|
try {
|
|
132
199
|
const dir = getDir();
|
|
133
200
|
await mkdir(dir, { recursive: true });
|
|
134
|
-
const cache = { models, timestamp: Date.now() };
|
|
201
|
+
const cache = { models, timestamp: Date.now(), etag };
|
|
135
202
|
await writeFile(join(dir, CACHE_FILE), JSON.stringify(cache, null, 2) + `
|
|
136
203
|
`, "utf8");
|
|
137
204
|
if (raw !== undefined) {
|
|
@@ -249,9 +316,24 @@ function resolveConfig(provider, authMetadata) {
|
|
|
249
316
|
const optBaseURL = resolveStringOption(provider?.options?.[PLEXUS_BASE_URL_OPTION]);
|
|
250
317
|
const legacyBaseURL = resolveStringOption(provider?.options?.baseURL);
|
|
251
318
|
const optApiKey = resolveStringOption(provider?.options?.apiKey);
|
|
319
|
+
const optSuppress = provider?.options?.["suppressModels"] ?? provider?.options?.["suppress"] ?? provider?.options?.["suppress_models"];
|
|
320
|
+
const envSuppress = getEnvSuppressedModels();
|
|
321
|
+
const configSuppress = parseSuppressionPatterns(optSuppress);
|
|
322
|
+
const suppressModels = [...envSuppress, ...configSuppress];
|
|
252
323
|
const baseURL = (envBaseURL ? rootURL(envBaseURL) : undefined) || (authBaseURL ? rootURL(authBaseURL) : undefined) || (optBaseURL ? rootURL(optBaseURL) : undefined) || (legacyBaseURL ? rootURL(legacyBaseURL) : undefined) || undefined;
|
|
253
324
|
const apiKey = (envApiKey ? envApiKey.trim() : undefined) || optApiKey || undefined;
|
|
254
|
-
return {
|
|
325
|
+
return {
|
|
326
|
+
baseURL: baseURL || undefined,
|
|
327
|
+
apiKey: apiKey || undefined,
|
|
328
|
+
...suppressModels.length > 0 ? { suppressModels } : {}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function getSuppressedModels(provider) {
|
|
332
|
+
const envSuppressed = getEnvSuppressedModels();
|
|
333
|
+
const providerObj = provider ?? {};
|
|
334
|
+
const providerOptions = typeof providerObj["options"] === "object" && providerObj["options"] !== null ? providerObj["options"] : {};
|
|
335
|
+
const optSuppressed = parseSuppressionPatterns(providerOptions["suppressModels"] ?? providerOptions["suppress"] ?? providerObj["suppressModels"] ?? providerObj["suppress"]);
|
|
336
|
+
return [...envSuppressed, ...optSuppressed];
|
|
255
337
|
}
|
|
256
338
|
|
|
257
339
|
// src/log.ts
|
|
@@ -353,11 +435,13 @@ function buildOutputModalities(model) {
|
|
|
353
435
|
}
|
|
354
436
|
return ["text"];
|
|
355
437
|
}
|
|
356
|
-
function buildModels(models, baseURL) {
|
|
438
|
+
function buildModels(models, baseURL, suppress) {
|
|
357
439
|
const result = {};
|
|
358
440
|
for (const m of models) {
|
|
359
441
|
if (!isChatModel(m))
|
|
360
442
|
continue;
|
|
443
|
+
if (isModelSuppressed(m, suppress))
|
|
444
|
+
continue;
|
|
361
445
|
const outputModalities = buildOutputModalities(m);
|
|
362
446
|
if (outputModalities === null)
|
|
363
447
|
continue;
|
|
@@ -497,7 +581,7 @@ function raceWithTimeout(promise, timeoutMs) {
|
|
|
497
581
|
});
|
|
498
582
|
});
|
|
499
583
|
}
|
|
500
|
-
function refreshModels(client, baseURL, log, apiKey, force = false) {
|
|
584
|
+
function refreshModels(client, baseURL, log, apiKey, force = false, suppress) {
|
|
501
585
|
if (!force && lastRefresh && Date.now() - lastRefresh.at < REFRESH_TTL_MS) {
|
|
502
586
|
log.info(`Using in-memory plexus model cache (${Object.keys(lastRefresh.models).length} models)`);
|
|
503
587
|
return Promise.resolve(lastRefresh.models);
|
|
@@ -506,15 +590,21 @@ function refreshModels(client, baseURL, log, apiKey, force = false) {
|
|
|
506
590
|
return inFlightRefresh;
|
|
507
591
|
const run = async () => {
|
|
508
592
|
const url = modelsUrl(baseURL);
|
|
509
|
-
const
|
|
510
|
-
const
|
|
593
|
+
const cached = await readCachedModels(client, suppress);
|
|
594
|
+
const { models: apiModels, raw, etag, notModified } = await fetchPlexusModels(apiKey ?? "", url, undefined, cached?.etag);
|
|
595
|
+
if (notModified && cached?.models) {
|
|
596
|
+
log.info(`Plexus models not modified (etag: ${cached.etag})`);
|
|
597
|
+
lastRefresh = { at: Date.now(), models: cached.models };
|
|
598
|
+
return cached.models;
|
|
599
|
+
}
|
|
600
|
+
const built = buildModels(apiModels, apiBase(baseURL), suppress);
|
|
511
601
|
for (const [id, model] of Object.entries(built)) {
|
|
512
602
|
const providerNpm = model.provider?.npm ?? OPENAI_COMPATIBLE_NPM;
|
|
513
603
|
const providerApi = model.provider?.api ?? "(missing)";
|
|
514
604
|
log.info(`Model mapping ${id}: npm=${providerNpm} api=${providerApi}`);
|
|
515
605
|
}
|
|
516
606
|
lastRefresh = { at: Date.now(), models: built };
|
|
517
|
-
writeCache(client, built, raw).catch(() => {});
|
|
607
|
+
writeCache(client, built, raw, etag).catch(() => {});
|
|
518
608
|
return built;
|
|
519
609
|
};
|
|
520
610
|
inFlightRefresh = run().finally(() => {
|
|
@@ -531,15 +621,17 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
531
621
|
const existing = cfg.provider[PLEXUS_PROVIDER_ID] ?? {};
|
|
532
622
|
const existingOptions = typeof existing["options"] === "object" && existing["options"] !== null ? existing["options"] : {};
|
|
533
623
|
const existingModels = typeof existing["models"] === "object" && existing["models"] !== null ? existing["models"] : null;
|
|
624
|
+
const suppress = getSuppressedModels(existing);
|
|
534
625
|
const { baseURL, apiKey } = resolveConfig(existing);
|
|
535
626
|
log.info(`Resolved plexus config: baseURL=${baseURL ?? "(missing)"} apiKey=${apiKey ? "present" : "missing"}`);
|
|
536
627
|
if (typeof existingOptions["baseURL"] === "string") {
|
|
537
628
|
log.warn(`Ignoring legacy provider.options.baseURL=${String(existingOptions["baseURL"])}`);
|
|
538
629
|
}
|
|
539
|
-
const cachedAsync = await readCachedModels(client);
|
|
630
|
+
const cachedAsync = await readCachedModels(client, suppress);
|
|
540
631
|
if (cachedAsync) {
|
|
541
|
-
log.info(`Loaded plexus cache with ${Object.keys(cachedAsync).length} models`);
|
|
632
|
+
log.info(`Loaded plexus cache with ${Object.keys(cachedAsync.models).length} models`);
|
|
542
633
|
}
|
|
634
|
+
const effectiveExistingModels = existingModels ? filterCachedModels(existingModels, suppress) : null;
|
|
543
635
|
const merged = {
|
|
544
636
|
...existing,
|
|
545
637
|
name: existing["name"] ?? PLEXUS_PROVIDER_NAME,
|
|
@@ -549,7 +641,7 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
549
641
|
...baseURL ? { [PLEXUS_BASE_URL_OPTION]: baseURL } : {},
|
|
550
642
|
...apiKey ? { apiKey } : {}
|
|
551
643
|
},
|
|
552
|
-
models:
|
|
644
|
+
models: (effectiveExistingModels && Object.keys(effectiveExistingModels).length > 0 ? effectiveExistingModels : null) ?? (cachedAsync ? toConfigModels(cachedAsync.models) : null) ?? {
|
|
553
645
|
[PLACEHOLDER_MODEL_ID]: {
|
|
554
646
|
id: PLACEHOLDER_MODEL_ID,
|
|
555
647
|
name: "Plexus (run /connect to configure)",
|
|
@@ -584,21 +676,22 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
584
676
|
provider: {
|
|
585
677
|
id: PLEXUS_PROVIDER_ID,
|
|
586
678
|
models: async (provider, hookCtx) => {
|
|
679
|
+
const suppress = getSuppressedModels(provider);
|
|
587
680
|
const authKey = hookCtx.auth?.type === "api" ? hookCtx.auth.key : undefined;
|
|
588
681
|
const { baseURL, apiKey } = resolveConfig(provider, authMetadata(hookCtx.auth));
|
|
589
682
|
const key = authKey ?? apiKey;
|
|
590
683
|
if (!baseURL) {
|
|
591
684
|
log.info("Provider hook skipped live refresh; baseURL missing");
|
|
592
|
-
const cached2 = await readCachedModels(client);
|
|
593
|
-
return cached2 ? toRuntimeModels(cached2, provider) : {};
|
|
685
|
+
const cached2 = await readCachedModels(client, suppress);
|
|
686
|
+
return cached2 ? toRuntimeModels(cached2.models, provider) : {};
|
|
594
687
|
}
|
|
595
|
-
const refreshPromise = refreshModels(client, baseURL, log, key);
|
|
688
|
+
const refreshPromise = refreshModels(client, baseURL, log, key, false, suppress);
|
|
596
689
|
const race = await raceWithTimeout(refreshPromise, CONFIG_HOOK_REFRESH_BUDGET_MS);
|
|
597
690
|
if (race.status === "resolved") {
|
|
598
691
|
log.info(`Provider hook loaded ${Object.keys(race.value).length} plexus models from ${baseURL}`);
|
|
599
692
|
return toRuntimeModels(race.value, provider);
|
|
600
693
|
}
|
|
601
|
-
const cached = await readCachedModels(client);
|
|
694
|
+
const cached = await readCachedModels(client, suppress);
|
|
602
695
|
if (race.status === "rejected") {
|
|
603
696
|
log.warn(`Provider hook live refresh failed, using cache: ${String(race.error)}`);
|
|
604
697
|
} else {
|
|
@@ -607,7 +700,7 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
607
700
|
log.warn(`Background plexus model refresh failed: ${String(e)}`);
|
|
608
701
|
});
|
|
609
702
|
}
|
|
610
|
-
return cached ? toRuntimeModels(cached, provider) : {};
|
|
703
|
+
return cached ? toRuntimeModels(cached.models, provider) : {};
|
|
611
704
|
}
|
|
612
705
|
},
|
|
613
706
|
"command.execute.before": async (input) => {
|
|
@@ -615,6 +708,7 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
615
708
|
return;
|
|
616
709
|
const configResponse = await client.config.get();
|
|
617
710
|
const provider = configResponse.data?.provider?.[PLEXUS_PROVIDER_ID];
|
|
711
|
+
const suppress = getSuppressedModels(provider);
|
|
618
712
|
const storedAuth = await readStoredAuth();
|
|
619
713
|
const { baseURL, apiKey } = resolveConfig(provider, storedAuth?.metadata);
|
|
620
714
|
const key = storedAuth?.key ?? apiKey;
|
|
@@ -623,7 +717,7 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
623
717
|
}
|
|
624
718
|
let models;
|
|
625
719
|
try {
|
|
626
|
-
models = await refreshModels(client, baseURL, log, key, true);
|
|
720
|
+
models = await refreshModels(client, baseURL, log, key, true, suppress);
|
|
627
721
|
} catch (e) {
|
|
628
722
|
throw new Error(`Plexus refresh failed: ${String(e)}. Existing cache left untouched.`);
|
|
629
723
|
}
|
|
@@ -692,6 +786,7 @@ export {
|
|
|
692
786
|
buildModels,
|
|
693
787
|
REFRESH_TTL_MS,
|
|
694
788
|
PlexusProviderPlugin,
|
|
789
|
+
PLEXUS_SUPPRESS_MODELS_OPTION,
|
|
695
790
|
PLEXUS_REFRESH_COMMAND,
|
|
696
791
|
PLEXUS_PROVIDER_NAME,
|
|
697
792
|
PLEXUS_PROVIDER_ID,
|
|
@@ -701,6 +796,10 @@ export {
|
|
|
701
796
|
PLACEHOLDER_MODEL_ID,
|
|
702
797
|
OPENAI_COMPATIBLE_NPM,
|
|
703
798
|
MODELS_FETCH_TIMEOUT_MS,
|
|
799
|
+
ENV_SUPPRESS_MODELS,
|
|
800
|
+
ENV_SUPPRESSED_MODELS,
|
|
801
|
+
ENV_IGNORE_MODELS,
|
|
802
|
+
ENV_EXCLUDE_MODELS,
|
|
704
803
|
ENV_BASE_URL,
|
|
705
804
|
ENV_API_URL,
|
|
706
805
|
ENV_API_KEY,
|