seo-intel 1.5.37 → 1.5.38

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.38 (2026-05-23)
4
+
5
+ ### Fix — LM Studio model count was always 0 (wrong endpoint + wrong parser)
6
+ The wizard showed `localhost:1234 LM Studio · 0 model(s) active` even when LM Studio had models loaded. Two bugs stacked:
7
+
8
+ 1. We were hitting `/api/v1/models` (LM Studio's native endpoint), not `/v1/models` (the OpenAI-compatible one).
9
+ 2. Even on the native endpoint, the response shape is `{ models: [{ key, loaded_instances }] }` — we were parsing it as `{ data: [{ id }] }` (OpenAI shape), so even when the call succeeded, the filter zeroed everything out.
10
+
11
+ Fix in `setup/checks.js`:
12
+ - Try `/v1/models` first (standard OpenAI-compat, listed under LM Studio's "OpenAI-compatible" Developer tab).
13
+ - Fall back to `/api/v1/models` if the OpenAI route is disabled in LM Studio settings.
14
+ - Parse both shapes: `data.data` (OpenAI) and `data.models` (LM Studio native). Identifier extracted via first-of `id | key | model | name`.
15
+
16
+ Verified against the user's live LM Studio (3 models surfaced correctly — Gemma 4 E2B, an uncensored variant, and an embedding model). Smoke 10/10.
17
+
3
18
  ## 1.5.37 (2026-05-23)
4
19
 
5
20
  ### Notify — native macOS / Linux notifications for pending problems
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seo-intel",
3
- "version": "1.5.37",
3
+ "version": "1.5.38",
4
4
  "description": "Local Ahrefs-style SEO competitor intelligence. Crawl → SQLite → cloud analysis.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
package/setup/checks.js CHANGED
@@ -80,15 +80,29 @@ export async function checkOllamaRemote(host) {
80
80
  export async function checkLmStudio(customUrl) {
81
81
  const host = customUrl || process.env.LMSTUDIO_URL || 'http://localhost:1234';
82
82
 
83
+ // LM Studio exposes TWO model endpoints with DIFFERENT response shapes:
84
+ // /v1/models OpenAI-compatible → { data: [{ id }] }
85
+ // /api/v1/models LM Studio native → { models: [{ key, loaded_instances }] }
86
+ // Try OpenAI-compat first (standard, smaller payload, listed under "OpenAI-
87
+ // compatible" tab in LM Studio Developer panel). Fall back to the native
88
+ // endpoint if the OpenAI one isn't enabled. Parse both shapes.
83
89
  try {
84
90
  const controller = new AbortController();
85
91
  const timeout = setTimeout(() => controller.abort(), 3000);
86
- const res = await fetch(`${host}/api/v1/models`, { signal: controller.signal });
92
+ let res = await fetch(`${host}/v1/models`, { signal: controller.signal });
93
+ if (!res.ok) {
94
+ // OpenAI-compat path off — try LM Studio native
95
+ res = await fetch(`${host}/api/v1/models`, { signal: controller.signal });
96
+ }
87
97
  clearTimeout(timeout);
88
98
 
89
99
  if (!res.ok) return { reachable: false, models: [], host };
90
- const data = await res.json().catch(() => ({ data: [] }));
91
- const models = (data.data || []).map(m => m.id || m.model).filter(Boolean);
100
+ const data = await res.json().catch(() => ({}));
101
+ // Support both shapes: OpenAI `data[]` and LM Studio native `models[]`.
102
+ const list = Array.isArray(data.data) ? data.data
103
+ : Array.isArray(data.models) ? data.models
104
+ : [];
105
+ const models = list.map(m => m.id || m.key || m.model || m.name).filter(Boolean);
92
106
  return { reachable: true, models, host };
93
107
  } catch {
94
108
  return { reachable: false, models: [], host };