@mcowger/opencode-plexus 1.3.9 → 1.4.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/index.js +30 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -120,23 +120,32 @@ function isChatModel(model) {
|
|
|
120
120
|
return !NON_CHAT_PATTERN.test(`${model.id} ${model.name ?? ""} ${apiHints}`);
|
|
121
121
|
}
|
|
122
122
|
var DEFAULT_MODELS_FETCH_TIMEOUT_MS = 1e4;
|
|
123
|
-
async function fetchPlexusModels(apiKey, modelsUrl, timeoutMs = DEFAULT_MODELS_FETCH_TIMEOUT_MS) {
|
|
123
|
+
async function fetchPlexusModels(apiKey, modelsUrl, timeoutMs = DEFAULT_MODELS_FETCH_TIMEOUT_MS, etag, signal) {
|
|
124
124
|
const controller = new AbortController;
|
|
125
125
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
126
|
+
const requestSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
|
|
126
127
|
try {
|
|
127
128
|
const headers = { Accept: "application/json" };
|
|
128
129
|
if (apiKey)
|
|
129
130
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
131
|
+
if (etag)
|
|
132
|
+
headers["If-None-Match"] = etag;
|
|
130
133
|
const res = await fetch(modelsUrl, {
|
|
131
134
|
headers,
|
|
132
|
-
signal:
|
|
135
|
+
signal: requestSignal
|
|
133
136
|
});
|
|
137
|
+
if (res.status === 304) {
|
|
138
|
+
return { models: [], notModified: true };
|
|
139
|
+
}
|
|
134
140
|
if (!res.ok) {
|
|
135
141
|
throw new Error(`Plexus models fetch failed: ${res.status} ${res.statusText}`);
|
|
136
142
|
}
|
|
137
143
|
const raw = await res.json();
|
|
138
|
-
|
|
144
|
+
const responseEtag = res.headers.get("etag") ?? undefined;
|
|
145
|
+
return { models: raw.data ?? [], raw, etag: responseEtag };
|
|
139
146
|
} catch (err) {
|
|
147
|
+
if (signal?.aborted)
|
|
148
|
+
throw err;
|
|
140
149
|
if (err instanceof Error && err.name === "AbortError") {
|
|
141
150
|
throw new Error(`Plexus models fetch timed out after ${timeoutMs}ms`);
|
|
142
151
|
}
|
|
@@ -178,18 +187,21 @@ async function readCachedModels(_client, suppress) {
|
|
|
178
187
|
const content = await readFile(join(dir, CACHE_FILE), "utf8");
|
|
179
188
|
const parsed = JSON.parse(content);
|
|
180
189
|
if (parsed && typeof parsed.models === "object" && !Array.isArray(parsed.models)) {
|
|
181
|
-
return
|
|
190
|
+
return {
|
|
191
|
+
models: filterCachedModels(parsed.models, suppress),
|
|
192
|
+
etag: typeof parsed.etag === "string" ? parsed.etag : undefined
|
|
193
|
+
};
|
|
182
194
|
}
|
|
183
195
|
return null;
|
|
184
196
|
} catch {
|
|
185
197
|
return null;
|
|
186
198
|
}
|
|
187
199
|
}
|
|
188
|
-
async function writeCache(_client, models, raw) {
|
|
200
|
+
async function writeCache(_client, models, raw, etag) {
|
|
189
201
|
try {
|
|
190
202
|
const dir = getDir();
|
|
191
203
|
await mkdir(dir, { recursive: true });
|
|
192
|
-
const cache = { models, timestamp: Date.now() };
|
|
204
|
+
const cache = { models, timestamp: Date.now(), etag };
|
|
193
205
|
await writeFile(join(dir, CACHE_FILE), JSON.stringify(cache, null, 2) + `
|
|
194
206
|
`, "utf8");
|
|
195
207
|
if (raw !== undefined) {
|
|
@@ -581,7 +593,13 @@ function refreshModels(client, baseURL, log, apiKey, force = false, suppress) {
|
|
|
581
593
|
return inFlightRefresh;
|
|
582
594
|
const run = async () => {
|
|
583
595
|
const url = modelsUrl(baseURL);
|
|
584
|
-
const
|
|
596
|
+
const cached = await readCachedModels(client, suppress);
|
|
597
|
+
const { models: apiModels, raw, etag, notModified } = await fetchPlexusModels(apiKey ?? "", url, undefined, cached?.etag);
|
|
598
|
+
if (notModified && cached?.models) {
|
|
599
|
+
log.info(`Plexus models not modified (etag: ${cached.etag})`);
|
|
600
|
+
lastRefresh = { at: Date.now(), models: cached.models };
|
|
601
|
+
return cached.models;
|
|
602
|
+
}
|
|
585
603
|
const built = buildModels(apiModels, apiBase(baseURL), suppress);
|
|
586
604
|
for (const [id, model] of Object.entries(built)) {
|
|
587
605
|
const providerNpm = model.provider?.npm ?? OPENAI_COMPATIBLE_NPM;
|
|
@@ -589,7 +607,7 @@ function refreshModels(client, baseURL, log, apiKey, force = false, suppress) {
|
|
|
589
607
|
log.info(`Model mapping ${id}: npm=${providerNpm} api=${providerApi}`);
|
|
590
608
|
}
|
|
591
609
|
lastRefresh = { at: Date.now(), models: built };
|
|
592
|
-
writeCache(client, built, raw).catch(() => {});
|
|
610
|
+
writeCache(client, built, raw, etag).catch(() => {});
|
|
593
611
|
return built;
|
|
594
612
|
};
|
|
595
613
|
inFlightRefresh = run().finally(() => {
|
|
@@ -614,7 +632,7 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
614
632
|
}
|
|
615
633
|
const cachedAsync = await readCachedModels(client, suppress);
|
|
616
634
|
if (cachedAsync) {
|
|
617
|
-
log.info(`Loaded plexus cache with ${Object.keys(cachedAsync).length} models`);
|
|
635
|
+
log.info(`Loaded plexus cache with ${Object.keys(cachedAsync.models).length} models`);
|
|
618
636
|
}
|
|
619
637
|
const effectiveExistingModels = existingModels ? filterCachedModels(existingModels, suppress) : null;
|
|
620
638
|
const merged = {
|
|
@@ -626,7 +644,7 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
626
644
|
...baseURL ? { [PLEXUS_BASE_URL_OPTION]: baseURL } : {},
|
|
627
645
|
...apiKey ? { apiKey } : {}
|
|
628
646
|
},
|
|
629
|
-
models: (effectiveExistingModels && Object.keys(effectiveExistingModels).length > 0 ? effectiveExistingModels : null) ?? (cachedAsync ? toConfigModels(cachedAsync) : null) ?? {
|
|
647
|
+
models: (effectiveExistingModels && Object.keys(effectiveExistingModels).length > 0 ? effectiveExistingModels : null) ?? (cachedAsync ? toConfigModels(cachedAsync.models) : null) ?? {
|
|
630
648
|
[PLACEHOLDER_MODEL_ID]: {
|
|
631
649
|
id: PLACEHOLDER_MODEL_ID,
|
|
632
650
|
name: "Plexus (run /connect to configure)",
|
|
@@ -668,7 +686,7 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
668
686
|
if (!baseURL) {
|
|
669
687
|
log.info("Provider hook skipped live refresh; baseURL missing");
|
|
670
688
|
const cached2 = await readCachedModels(client, suppress);
|
|
671
|
-
return cached2 ? toRuntimeModels(cached2, provider) : {};
|
|
689
|
+
return cached2 ? toRuntimeModels(cached2.models, provider) : {};
|
|
672
690
|
}
|
|
673
691
|
const refreshPromise = refreshModels(client, baseURL, log, key, false, suppress);
|
|
674
692
|
const race = await raceWithTimeout(refreshPromise, CONFIG_HOOK_REFRESH_BUDGET_MS);
|
|
@@ -685,7 +703,7 @@ var PlexusProviderPlugin = async (ctx) => {
|
|
|
685
703
|
log.warn(`Background plexus model refresh failed: ${String(e)}`);
|
|
686
704
|
});
|
|
687
705
|
}
|
|
688
|
-
return cached ? toRuntimeModels(cached, provider) : {};
|
|
706
|
+
return cached ? toRuntimeModels(cached.models, provider) : {};
|
|
689
707
|
}
|
|
690
708
|
},
|
|
691
709
|
"command.execute.before": async (input) => {
|