@fro.bot/systematic 2.14.2 → 2.14.4
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 +9 -5
- package/dist/lib/model-availability.d.ts +15 -9
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -717,14 +717,14 @@ function readFallbackCache() {
|
|
|
717
717
|
if (openCodeModelsUrl) {
|
|
718
718
|
const urlDerivedPath = path5.join(cacheDir, `models-${fastHash(openCodeModelsUrl)}.json`);
|
|
719
719
|
const urlResult = readModelsFromCache(urlDerivedPath);
|
|
720
|
-
if (urlResult !== null) {
|
|
720
|
+
if (urlResult !== null && urlResult.size > 0) {
|
|
721
721
|
return { status: "cache", models: urlResult };
|
|
722
722
|
}
|
|
723
723
|
return emptyAvailability();
|
|
724
724
|
}
|
|
725
725
|
const defaultPath = path5.join(cacheDir, MODELS_JSON_FILENAME);
|
|
726
726
|
const defaultResult = readModelsFromCache(defaultPath);
|
|
727
|
-
if (defaultResult !== null) {
|
|
727
|
+
if (defaultResult !== null && defaultResult.size > 0) {
|
|
728
728
|
return { status: "cache", models: defaultResult };
|
|
729
729
|
}
|
|
730
730
|
return emptyAvailability();
|
|
@@ -767,9 +767,13 @@ async function getAvailableModels(client, options = {}) {
|
|
|
767
767
|
if (response.error !== undefined || response.data === undefined) {
|
|
768
768
|
return readFallbackCache();
|
|
769
769
|
}
|
|
770
|
+
const models = buildSetFromProviders(response.data.providers);
|
|
771
|
+
if (models.size === 0) {
|
|
772
|
+
return emptyAvailability();
|
|
773
|
+
}
|
|
770
774
|
return {
|
|
771
775
|
status: "api",
|
|
772
|
-
models
|
|
776
|
+
models
|
|
773
777
|
};
|
|
774
778
|
}
|
|
775
779
|
|
|
@@ -1088,6 +1092,8 @@ function createConfigHandler(deps) {
|
|
|
1088
1092
|
const bundledSkills = collectSkillsAsCommands(bundledSkillsDir, systematicConfig.disabled_skills);
|
|
1089
1093
|
const enabledSkillNames = collectEnabledSkillNames(bundledSkillsDir, systematicConfig.disabled_skills);
|
|
1090
1094
|
const inventory = buildBundledAgentInventory(bundledAgentsDir2, systematicConfig.disabled_agents);
|
|
1095
|
+
const availability = deps.client ? await getAvailableModels(deps.client) : undefined;
|
|
1096
|
+
const availabilitySet = availability && availability.status !== "unknown" ? availability.models : undefined;
|
|
1091
1097
|
assertSourceCategoryModelCoverage(inventory.categories);
|
|
1092
1098
|
const validatedOverlays = validateAgentOverlays({
|
|
1093
1099
|
inventory,
|
|
@@ -1096,8 +1102,6 @@ function createConfigHandler(deps) {
|
|
|
1096
1102
|
enabledSkills: enabledSkillNames
|
|
1097
1103
|
});
|
|
1098
1104
|
const resolvedOverlays = resolveAgentOverlaySet(validatedOverlays);
|
|
1099
|
-
const availability = deps.client ? await getAvailableModels(deps.client) : undefined;
|
|
1100
|
-
const availabilitySet = availability && availability.status !== "unknown" ? availability.models : undefined;
|
|
1101
1105
|
const bundledAgents = collectAgents(bundledAgentsDir2, systematicConfig.disabled_agents, nativeAgents, resolvedOverlays, availabilitySet);
|
|
1102
1106
|
const bundledCommands = collectCommands(bundledCommandsDir, systematicConfig.disabled_commands);
|
|
1103
1107
|
const bundledAgentKeys = new Set(Object.keys(bundledAgents));
|
|
@@ -22,16 +22,22 @@ export interface OpencodeClientLike {
|
|
|
22
22
|
* Outcome of model availability discovery.
|
|
23
23
|
*
|
|
24
24
|
* - `api`: The OpenCode server's `/config/providers` endpoint responded with
|
|
25
|
-
* a connected-providers payload
|
|
26
|
-
*
|
|
25
|
+
* a connected-providers payload AND `models` is non-empty. An authoritatively
|
|
26
|
+
* empty response (`data.providers = []`, or providers present with zero
|
|
27
|
+
* models) collapses to `'unknown'` instead — see below — because the
|
|
28
|
+
* operational consequence is identical and downstream consumers should treat
|
|
29
|
+
* both cases the same way.
|
|
27
30
|
* - `cache`: The API call failed (error envelope, thrown, or timed out) and
|
|
28
|
-
* the local `models.json` cache was readable. `models`
|
|
29
|
-
* OpenCode last wrote to disk.
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
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
|
+
* - `unknown`: Either both the API call and the cache fallback failed (cache
|
|
36
|
+
* missing, unreadable, corrupt, or schema-mismatched), OR the API call
|
|
37
|
+
* succeeded with zero usable models. Resolution should degrade gracefully —
|
|
38
|
+
* callers should treat `unknown` as a signal to skip source-default model
|
|
39
|
+
* pinning so users do not get agents pinned to inaccessible models.
|
|
40
|
+
* `models` is the empty set.
|
|
35
41
|
*/
|
|
36
42
|
export type DiscoveryStatus = 'api' | 'cache' | 'unknown';
|
|
37
43
|
export interface ModelAvailability {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fro.bot/systematic",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.4",
|
|
4
4
|
"description": "Structured engineering workflows for OpenCode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://fro.bot/systematic",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@opencode-ai/sdk": "1.14.48",
|
|
69
69
|
"@types/bun": "latest",
|
|
70
70
|
"@types/js-yaml": "4.0.9",
|
|
71
|
-
"@types/node": "24.12.
|
|
71
|
+
"@types/node": "24.12.4",
|
|
72
72
|
"ajv": "8.20.0",
|
|
73
73
|
"ajv-formats": "3.0.1",
|
|
74
74
|
"conventional-changelog-conventionalcommits": "9.3.1",
|