offgrid-ai 0.6.4 → 0.6.6
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 +1 -1
- package/src/backends.mjs +20 -10
- package/src/cli.mjs +7 -25
- package/src/profiles.mjs +1 -0
- package/src/scan.mjs +1 -0
package/package.json
CHANGED
package/src/backends.mjs
CHANGED
|
@@ -117,16 +117,18 @@ async function scanOmlxModels() {
|
|
|
117
117
|
if (!response.ok) return [];
|
|
118
118
|
const body = await response.json();
|
|
119
119
|
if (!Array.isArray(body?.data)) return [];
|
|
120
|
-
return body.data
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
return body.data
|
|
121
|
+
.filter((model) => isChatOmlxModel(model))
|
|
122
|
+
.map((model) => ({
|
|
123
|
+
id: model.id,
|
|
124
|
+
label: omlxLabel(model.id),
|
|
125
|
+
aliasSuggestion: model.id,
|
|
126
|
+
sizeBytes: 0,
|
|
127
|
+
quant: null,
|
|
128
|
+
family: null,
|
|
129
|
+
backend: "omlx",
|
|
130
|
+
source: "omlx",
|
|
131
|
+
})).sort((a, b) => a.label.localeCompare(b.label));
|
|
130
132
|
} catch {
|
|
131
133
|
return [];
|
|
132
134
|
}
|
|
@@ -141,6 +143,14 @@ function isLocalOllamaModel(model) {
|
|
|
141
143
|
return true;
|
|
142
144
|
}
|
|
143
145
|
|
|
146
|
+
function isChatOmlxModel(model) {
|
|
147
|
+
if (typeof model?.id !== "string" || !model.id.trim()) return false;
|
|
148
|
+
const type = String(model.type ?? model.model_type ?? "").toLowerCase();
|
|
149
|
+
if (["embedding", "embeddings", "reranker", "tool", "converter"].includes(type)) return false;
|
|
150
|
+
if (Object.hasOwn(model, "max_model_len") && model.max_model_len === null) return false;
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
|
|
144
154
|
function ollamaLabel(name) {
|
|
145
155
|
return name.replace(/[-_]/g, " ").replace(/^gemma\b/i, "Gemma").replace(/^qwen/i, "Qwen");
|
|
146
156
|
}
|
package/src/cli.mjs
CHANGED
|
@@ -284,7 +284,7 @@ function optionTag(text, color, width) {
|
|
|
284
284
|
function optionStatusTag(kind) {
|
|
285
285
|
const statuses = {
|
|
286
286
|
running: ["RUNNING", pc.green],
|
|
287
|
-
ready: ["
|
|
287
|
+
ready: ["READY", pc.green],
|
|
288
288
|
missing: ["FILE MISSING", pc.red],
|
|
289
289
|
setup: ["NEEDS SETUP", pc.yellow],
|
|
290
290
|
};
|
|
@@ -307,11 +307,7 @@ function optionLabel({ status, source, name, details = [] }) {
|
|
|
307
307
|
return [status, source, pc.bold(name), ...details].filter(Boolean).join(OPTION_SEPARATOR);
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
-
function
|
|
311
|
-
return parts.filter(Boolean).join(" · ");
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function modelSelectOption(item, { runningProfilesNow, drafters }) {
|
|
310
|
+
function modelSelectOption(item, { runningProfilesNow }) {
|
|
315
311
|
if (item.type === "profile") {
|
|
316
312
|
const { profile } = item;
|
|
317
313
|
const backend = backendFor(profile.backend);
|
|
@@ -319,41 +315,27 @@ function modelSelectOption(item, { runningProfilesNow, drafters }) {
|
|
|
319
315
|
const fileMissing = item.fileMissing;
|
|
320
316
|
const status = optionStatusTag(fileMissing ? "missing" : running ? "running" : "ready");
|
|
321
317
|
const source = optionSourceTag(profile.backend, backend.label);
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
if (profile.drafterPath) mtpLabel = pc.green("MTP on");
|
|
325
|
-
else if (drafters ? matchDrafter(profile.modelPath, drafters) : null) mtpLabel = pc.yellow("MTP available");
|
|
326
|
-
else if (caps.architecture === "gemma4") mtpLabel = pc.yellow("MTP needs drafter");
|
|
327
|
-
const ctxLabel = profile.flags?.ctxSize ? pc.dim(`${(profile.flags.ctxSize / 1000).toFixed(0)}k ctx`) : null;
|
|
328
|
-
const label = optionLabel({ status, source, name: profile.label, details: [ctxLabel, mtpLabel] });
|
|
329
|
-
return { value: itemKey(item), label, hint: optionHint([profile.modelAlias, humanCapabilitySummary(caps), profile.baseUrl]) };
|
|
318
|
+
const label = optionLabel({ status, source, name: profile.label });
|
|
319
|
+
return { value: itemKey(item), label };
|
|
330
320
|
}
|
|
331
321
|
if (item.type === "new") {
|
|
332
|
-
const { model
|
|
333
|
-
const caps = detectCapabilities(model.path, model.mmprojPath);
|
|
334
|
-
const mtpAvailable = caps.mtp || Boolean(drafter);
|
|
335
|
-
let mtpLabel;
|
|
336
|
-
if (mtpAvailable) mtpLabel = pc.green("MTP available");
|
|
337
|
-
else if (caps.architecture === "gemma4") mtpLabel = pc.yellow("MTP needs drafter");
|
|
322
|
+
const { model } = item;
|
|
338
323
|
const label = optionLabel({
|
|
339
324
|
status: optionStatusTag("setup"),
|
|
340
325
|
source: optionSourceTag("gguf", "GGUF file"),
|
|
341
326
|
name: model.label,
|
|
342
|
-
details: [pc.dim(formatBytes(model.sizeBytes)), mtpLabel],
|
|
343
327
|
});
|
|
344
|
-
return { value: itemKey(item), label
|
|
328
|
+
return { value: itemKey(item), label };
|
|
345
329
|
}
|
|
346
330
|
// managed
|
|
347
331
|
const { model, backendId } = item;
|
|
348
332
|
const backend = BACKENDS[backendId];
|
|
349
|
-
const details = [model.quant ? pc.dim(model.quant) : null, model.sizeBytes ? pc.dim(formatBytes(model.sizeBytes)) : null];
|
|
350
333
|
const label = optionLabel({
|
|
351
334
|
status: optionStatusTag("setup"),
|
|
352
335
|
source: optionSourceTag(backendId, backend.label),
|
|
353
336
|
name: model.label,
|
|
354
|
-
details,
|
|
355
337
|
});
|
|
356
|
-
return { value: itemKey(item), label
|
|
338
|
+
return { value: itemKey(item), label };
|
|
357
339
|
}
|
|
358
340
|
|
|
359
341
|
function actionsForItem(item) {
|
package/src/profiles.mjs
CHANGED
|
@@ -150,6 +150,7 @@ export async function createProfileFromModel(model, backendId, drafterPath) {
|
|
|
150
150
|
backend,
|
|
151
151
|
providerId: backend,
|
|
152
152
|
modelAlias: model.aliasSuggestion,
|
|
153
|
+
source: model.source,
|
|
153
154
|
modelPath: model.path,
|
|
154
155
|
mmprojPath: model.mmprojPath,
|
|
155
156
|
drafterPath: drafterPath ?? null,
|