@fro.bot/systematic 2.14.3 → 2.14.5
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 +20 -9
- package/dist/lib/model-availability.d.ts +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -634,6 +634,7 @@ function emptyAvailability() {
|
|
|
634
634
|
var MAX_CACHE_FILE_BYTES = 16 * 1024 * 1024;
|
|
635
635
|
var DEFAULT_API_TIMEOUT_MS = 1500;
|
|
636
636
|
var MODELS_JSON_FILENAME = "models.json";
|
|
637
|
+
var availabilityCache = new WeakMap;
|
|
637
638
|
function resolveCacheDir() {
|
|
638
639
|
const xdgCacheHome = process.env.XDG_CACHE_HOME?.trim();
|
|
639
640
|
const cacheBase = xdgCacheHome && path5.isAbsolute(xdgCacheHome) ? xdgCacheHome : path5.join(os2.homedir(), ".cache");
|
|
@@ -717,14 +718,14 @@ function readFallbackCache() {
|
|
|
717
718
|
if (openCodeModelsUrl) {
|
|
718
719
|
const urlDerivedPath = path5.join(cacheDir, `models-${fastHash(openCodeModelsUrl)}.json`);
|
|
719
720
|
const urlResult = readModelsFromCache(urlDerivedPath);
|
|
720
|
-
if (urlResult !== null) {
|
|
721
|
+
if (urlResult !== null && urlResult.size > 0) {
|
|
721
722
|
return { status: "cache", models: urlResult };
|
|
722
723
|
}
|
|
723
724
|
return emptyAvailability();
|
|
724
725
|
}
|
|
725
726
|
const defaultPath = path5.join(cacheDir, MODELS_JSON_FILENAME);
|
|
726
727
|
const defaultResult = readModelsFromCache(defaultPath);
|
|
727
|
-
if (defaultResult !== null) {
|
|
728
|
+
if (defaultResult !== null && defaultResult.size > 0) {
|
|
728
729
|
return { status: "cache", models: defaultResult };
|
|
729
730
|
}
|
|
730
731
|
return emptyAvailability();
|
|
@@ -739,9 +740,19 @@ function buildSetFromProviders(providers) {
|
|
|
739
740
|
return result;
|
|
740
741
|
}
|
|
741
742
|
async function getAvailableModels(client, options = {}) {
|
|
743
|
+
const cached = availabilityCache.get(client);
|
|
744
|
+
if (cached !== undefined) {
|
|
745
|
+
return cached;
|
|
746
|
+
}
|
|
747
|
+
const cacheAndReturn = (envelope) => {
|
|
748
|
+
if (envelope.status !== "unknown") {
|
|
749
|
+
availabilityCache.set(client, envelope);
|
|
750
|
+
}
|
|
751
|
+
return envelope;
|
|
752
|
+
};
|
|
742
753
|
const timeoutMs = options.apiTimeoutMs === undefined ? DEFAULT_API_TIMEOUT_MS : options.apiTimeoutMs;
|
|
743
754
|
if (typeof client.config?.providers !== "function") {
|
|
744
|
-
return readFallbackCache();
|
|
755
|
+
return cacheAndReturn(readFallbackCache());
|
|
745
756
|
}
|
|
746
757
|
const apiCall = client.config.providers();
|
|
747
758
|
let response;
|
|
@@ -757,24 +768,24 @@ async function getAvailableModels(client, options = {}) {
|
|
|
757
768
|
const raced = await Promise.race([apiCall, timeoutPromise]);
|
|
758
769
|
if (raced === TIMEOUT_SENTINEL) {
|
|
759
770
|
console.warn(`[systematic] client.config.providers() exceeded ${timeoutMs}ms; falling back to models.json cache.`);
|
|
760
|
-
return readFallbackCache();
|
|
771
|
+
return cacheAndReturn(readFallbackCache());
|
|
761
772
|
}
|
|
762
773
|
response = raced;
|
|
763
774
|
}
|
|
764
775
|
} catch {
|
|
765
|
-
return readFallbackCache();
|
|
776
|
+
return cacheAndReturn(readFallbackCache());
|
|
766
777
|
}
|
|
767
778
|
if (response.error !== undefined || response.data === undefined) {
|
|
768
|
-
return readFallbackCache();
|
|
779
|
+
return cacheAndReturn(readFallbackCache());
|
|
769
780
|
}
|
|
770
781
|
const models = buildSetFromProviders(response.data.providers);
|
|
771
782
|
if (models.size === 0) {
|
|
772
|
-
return emptyAvailability();
|
|
783
|
+
return cacheAndReturn(emptyAvailability());
|
|
773
784
|
}
|
|
774
|
-
return {
|
|
785
|
+
return cacheAndReturn({
|
|
775
786
|
status: "api",
|
|
776
787
|
models
|
|
777
|
-
};
|
|
788
|
+
});
|
|
778
789
|
}
|
|
779
790
|
|
|
780
791
|
// src/lib/config-handler.ts
|
|
@@ -28,10 +28,10 @@ export interface OpencodeClientLike {
|
|
|
28
28
|
* operational consequence is identical and downstream consumers should treat
|
|
29
29
|
* both cases the same way.
|
|
30
30
|
* - `cache`: The API call failed (error envelope, thrown, or timed out) and
|
|
31
|
-
* the local `models.json` cache was readable. `models`
|
|
32
|
-
* OpenCode last wrote to disk.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
31
|
+
* the local `models.json` cache was readable AND non-empty. `models`
|
|
32
|
+
* reflects whatever OpenCode last wrote to disk. A cache that loads
|
|
33
|
+
* successfully but produces a zero-size set collapses to `'unknown'` for
|
|
34
|
+
* the same operational reason an empty API response does.
|
|
35
35
|
* - `unknown`: Either both the API call and the cache fallback failed (cache
|
|
36
36
|
* missing, unreadable, corrupt, or schema-mismatched), OR the API call
|
|
37
37
|
* succeeded with zero usable models. Resolution should degrade gracefully —
|