offgrid-ai 0.5.3 → 0.5.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.mjs +29 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "offgrid-ai",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "Privacy-first CLI for running local LLMs — discover, configure, run, benchmark",
5
5
  "author": "Eeshan Srivastava (https://eeshans.com)",
6
6
  "type": "module",
package/src/cli.mjs CHANGED
@@ -181,40 +181,37 @@ async function modelCommandCenter(initialCatalog) {
181
181
  return;
182
182
  }
183
183
 
184
+ const catalog = initialCatalog.newModels ? initialCatalog : await loadModelCatalog();
185
+ const normalized = normalizeCatalog(catalog);
186
+ const allItems = buildCatalogItems(normalized);
187
+ if (allItems.length === 0) { console.log(pc.dim("No models found.")); return; }
188
+ const runningProfilesNow = [];
189
+ for (const profile of normalized.profiles) {
190
+ if (await isProfileRunning(profile)) runningProfilesNow.push(profile);
191
+ }
192
+ const fileMissingCount = normalized.profiles.filter((p) => isProfileFileMissing(p)).length;
193
+ const summaryBorder = fileMissingCount > 0 ? pc.red : normalized.newModels.length > 0 ? pc.yellow : pc.dim;
194
+ console.log("\n" + renderCard("Your local AI workspace", renderRows([
195
+ ["Setups", `${normalized.profiles.length} saved`],
196
+ ["Need setup", normalized.newModels.length > 0 ? pc.yellow(`${normalized.newModels.length} model${normalized.newModels.length === 1 ? "" : "s"}`) : pc.dim("none")],
197
+ ["Running", runningProfilesNow.length > 0 ? pc.green(String(runningProfilesNow.length)) : pc.dim("none")],
198
+ ["File missing", fileMissingCount > 0 ? pc.red(`${fileMissingCount} setup${fileMissingCount === 1 ? "" : "s"}`) : pc.dim("none")],
199
+ ]), { formatBorder: summaryBorder }));
200
+
201
+ printModelCards(allItems, { runningProfilesNow, drafters: normalized.drafters });
202
+
184
203
  const prompt = createPrompt();
185
204
  try {
186
- while (true) {
187
- const catalog = await loadModelCatalog();
188
- const normalized = normalizeCatalog(catalog);
189
- const allItems = buildCatalogItems(normalized);
190
- if (allItems.length === 0) { console.log(pc.dim("No models found.")); break; }
191
- const runningProfilesNow = [];
192
- for (const profile of normalized.profiles) {
193
- if (await isProfileRunning(profile)) runningProfilesNow.push(profile);
194
- }
195
- const fileMissingCount = normalized.profiles.filter((p) => isProfileFileMissing(p)).length;
196
- const summaryBorder = fileMissingCount > 0 ? pc.red : normalized.newModels.length > 0 ? pc.yellow : pc.dim;
197
- console.log("\n" + renderCard("Your local AI workspace", renderRows([
198
- ["Setups", `${normalized.profiles.length} saved`],
199
- ["Need setup", normalized.newModels.length > 0 ? pc.yellow(`${normalized.newModels.length} model${normalized.newModels.length === 1 ? "" : "s"}`) : pc.dim("none")],
200
- ["Running", runningProfilesNow.length > 0 ? pc.green(String(runningProfilesNow.length)) : pc.dim("none")],
201
- ["File missing", fileMissingCount > 0 ? pc.red(`${fileMissingCount} setup${fileMissingCount === 1 ? "" : "s"}`) : pc.dim("none")],
202
- ]), { formatBorder: summaryBorder }));
203
-
204
- // Show model cards for all items
205
- printModelCards(allItems, { runningProfilesNow, drafters: normalized.drafters });
206
-
207
- const options = allItems.map((item) => modelSelectOption(item, { runningProfilesNow, drafters: normalized.drafters }));
208
- const selected = await prompt.choice("Select a model", options);
209
- if (!selected) break;
210
- const item = allItems.find((i) => itemKey(i) === selected);
211
- if (!item) break;
212
-
213
- const actions = actionsForItem(item);
214
- const action = await prompt.choice(item.label, actions, actions[0].value);
215
- if (!action) continue;
216
- await performAction(prompt, action, item);
217
- }
205
+ const options = allItems.map((item) => modelSelectOption(item, { runningProfilesNow, drafters: normalized.drafters }));
206
+ const selected = await prompt.choice("Select a model", options);
207
+ if (!selected) return;
208
+ const item = allItems.find((i) => itemKey(i) === selected);
209
+ if (!item) return;
210
+
211
+ const actions = actionsForItem(item);
212
+ const action = await prompt.choice(item.label, actions, actions[0].value);
213
+ if (!action) return;
214
+ await performAction(prompt, action, item);
218
215
  } finally {
219
216
  prompt.close();
220
217
  }