mslxdff 0.1.100 → 0.1.101

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mslxdff",
3
- "version": "0.1.100",
3
+ "version": "0.1.101",
4
4
  "description": "测试项目,请勿使用。",
5
5
  "type": "module",
6
6
  "bin": {
@@ -84,7 +84,7 @@ export async function handleSetto(args) {
84
84
  if (!norm || norm === "auto") continue;
85
85
  // 首次循环也同步 preferred(保持 daemon 热重载语义)
86
86
  if (rawId === list[0]) savePreferredModel(norm);
87
- const r = await syncToOpencode({ id: norm, token, port, file, keep: pruneKeep() });
87
+ const r = await syncToOpencode({ id: norm, token, port, file, keep: pruneKeep(), ensureAll: pruneKeep() });
88
88
  if (r.action === "inserted") inserted++; else updated++;
89
89
  prunedTotal += r.pruned || 0;
90
90
  console.log(` ${r.action} "${r.id}" -> ${r.internal} @ ${file}`);
@@ -156,8 +156,9 @@ export async function handleSetto(args) {
156
156
  const envPort = Number(process.env.MSLXDFF_PORT);
157
157
  const port = persisted !== null ? persisted : (Number.isInteger(envPort) && envPort > 0 ? envPort : 8989);
158
158
  const file = opencodeConfigPath();
159
- const r = await syncToOpencode({ id, token, port, file, keep: pruneKeep() });
159
+ const r = await syncToOpencode({ id, token, port, file, keep: pruneKeep(), ensureAll: pruneKeep() });
160
160
  console.log(`synced to opencode: ${r.action} "${r.id}" @ ${file}`);
161
+ if (r.backfilled) console.log(` backfilled ${r.backfilled} 个 picks 模型(此前 pick 了但未同步过,现已补齐)`);
161
162
  if (r.pruned) console.log(` pruned ${r.pruned} 个失效模型(未在 picks,不再于 opencode 显示)`);
162
163
  console.log(` url: http://127.0.0.1:${port}/v1`);
163
164
  console.log(` opencode 选 mslxdff/${r.id} 直达本地 ${r.internal}${r.storageKey !== r.internal ? ` (dash→${r.internal} 自动映射)` : ""}`);
@@ -78,7 +78,43 @@ export function pruneOpencodeModels(models, keep, currentKey) {
78
78
  return pruned;
79
79
  }
80
80
 
81
- export async function syncToOpencode({ id, token, port, file, keep } = {}) {
81
+ // 补齐:把 ensureAll(picks 口径)里缺失的键写入 models(slash dash + alias 注册)。
82
+ // 返回 { nextModels, backfilled };ensureAll 非数组或为空时原样返回(backfilled=0)。
83
+ // 注意:需在剪枝之前调用——先补 picks 缺失,再剪 picks 外旧键,结果集恰为 picks ∪ currentKey。
84
+ export async function ensureAllOpencodeModels(models, ensureAll) {
85
+ if (!Array.isArray(ensureAll) || !ensureAll.length || !models || typeof models !== "object") {
86
+ return { nextModels: models, backfilled: 0 };
87
+ }
88
+ const existing = new Set(Object.keys(models).map(normalizeOpencodeKey));
89
+ let backfilled = 0;
90
+ let aliasDirty = false;
91
+ for (const raw of ensureAll) {
92
+ const internal = toInternalId(String(raw || "").trim());
93
+ if (!internal || internal === "auto") continue;
94
+ const storageKey = internal.includes("/") ? internal.replace(/\//g, "-") : internal;
95
+ if (!storageKey || existing.has(storageKey)) continue;
96
+ models[storageKey] = { name: storageKey };
97
+ existing.add(storageKey);
98
+ backfilled++;
99
+ if (internal.includes("/") && storageKey !== internal) {
100
+ try {
101
+ const { loadModelAliases, registerModelAlias } = await import("./providers/model-id.js");
102
+ loadModelAliases();
103
+ registerModelAlias(storageKey, internal);
104
+ aliasDirty = true;
105
+ } catch {}
106
+ }
107
+ }
108
+ if (aliasDirty) {
109
+ try {
110
+ const { persistModelAliases } = await import("./providers/model-id.js");
111
+ persistModelAliases();
112
+ } catch {}
113
+ }
114
+ return { nextModels: models, backfilled };
115
+ }
116
+
117
+ export async function syncToOpencode({ id, token, port, file, keep, ensureAll } = {}) {
82
118
  const targetFile = file || opencodeConfigPath();
83
119
  const normalizedRaw = String(id || "").trim();
84
120
  if (!normalizedRaw) throw new Error("model id required");
@@ -119,6 +155,7 @@ export async function syncToOpencode({ id, token, port, file, keep } = {}) {
119
155
  let action;
120
156
  let effectiveId = storageKey;
121
157
  let pruned = 0;
158
+ let backfilled = 0;
122
159
  if (oldProvider) {
123
160
  const oldModels = oldProvider.models && typeof oldProvider.models === "object" && !Array.isArray(oldProvider.models)
124
161
  ? oldProvider.models
@@ -158,6 +195,8 @@ export async function syncToOpencode({ id, token, port, file, keep } = {}) {
158
195
  effectiveId = storageKey;
159
196
  action = "inserted";
160
197
  }
198
+ const ensured = await ensureAllOpencodeModels(nextModels, ensureAll);
199
+ backfilled = ensured.backfilled;
161
200
  pruned = pruneOpencodeModels(nextModels, keep, storageKey);
162
201
  const nextProvider = {
163
202
  ...oldProvider,
@@ -177,6 +216,8 @@ export async function syncToOpencode({ id, token, port, file, keep } = {}) {
177
216
  if (!data.provider.mslxdff.models[storageKey]) {
178
217
  data.provider.mslxdff.models = { [storageKey]: { name: storageKey } };
179
218
  }
219
+ const ensured = await ensureAllOpencodeModels(data.provider.mslxdff.models, ensureAll);
220
+ backfilled = ensured.backfilled;
180
221
  action = "inserted";
181
222
  }
182
223
 
@@ -208,5 +249,5 @@ export async function syncToOpencode({ id, token, port, file, keep } = {}) {
208
249
  }
209
250
  } catch {}
210
251
 
211
- return { action, file: targetFile, id: effectiveId, alias: storageKey, internal, corrupted, storageKey, pruned };
252
+ return { action, file: targetFile, id: effectiveId, alias: storageKey, internal, corrupted, storageKey, pruned, backfilled };
212
253
  }