llm_meta_widget 0.15.0 → 0.15.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8797cb824bc5421990348a5de7fabd7eb95a0ec0c10f8e2d579d29d3483e7b29
4
- data.tar.gz: 8151a9ab5e27e0e1bd1f46d62750e2a41137660d65c501713e9a10e94269858f
3
+ metadata.gz: 863b128096d9e0813388bb13a03d96a8f2b0f202f2aa5c33a27bdd0a48416c7b
4
+ data.tar.gz: e14113a514e1fa7ffb09e067cc44150e32e90a61fb5dd80946b9d7cfb34c6ad6
5
5
  SHA512:
6
- metadata.gz: 12d33498cb17917ebc7f6a5950185b003267c52eab06f50e9632d36e5fd7e9c1bfe54d18134be7bc5e9082ff4c5e087769b0235983ff72aa6ec3dbd8461641af
7
- data.tar.gz: 0f2975b8f85714bb11e64b43192755e26b61f90a9a80e6f20871895a76e292bfbb3f245c7e7f679e81331f1ab9be7d0362e91b8ce4e32b96d16ac10ce9eb8ded
6
+ metadata.gz: c1c3f21142b8de93b5a8216472aa700ac7fd72c589ca810f95eb8e3d368a60045974cec8f56a8e6fd64803da7b6a90a18be296312b7f3dc6f42c3c252ccf0f62
7
+ data.tar.gz: 5ee508999c3a2fe61e26f258b4362e4fac981097d7a3c5a375d6dcfe129e75f0d415d0a26d1404c3d2bc99e7f140347851b55609ca157f25bdb0b889b3fe1703
data/CHANGELOG.md CHANGED
@@ -3,6 +3,57 @@
3
3
  This file starts at 0.8.0, the first release with a breaking change worth
4
4
  calling out. Earlier releases are in the git history (`git log --oneline v0.7.6`).
5
5
 
6
+ ## 0.15.2
7
+
8
+ ### A page that hides the model picker now learns the context window too
9
+
10
+ Both requests for the hub's model list sat inside the branches that fill the
11
+ model picker. A page that pins one model and hides the picker therefore never
12
+ learned that model's context window — and hiding the picker is a reasonable
13
+ choice when the host has already chosen the model.
14
+
15
+ Without a window the resource budget falls back to its 8 KB floor, so a page's
16
+ reference data is reported as skipped even when it would have fitted, and
17
+ oversized tool results are neither trimmed nor evicted, because each of those
18
+ steps returns its input unchanged when it has no window to spend. Release
19
+ 0.15.1 could not even warn about it: the warning there fires when a request
20
+ comes back unusable, and here no request was made.
21
+
22
+ The model list is now fetched whenever the hub is the provider, and only
23
+ filling the picker remains conditional. A page configured to talk straight to
24
+ Ollama is left alone, since there is no such endpoint to ask.
25
+
26
+ The widget also says so once, in the browser console, if a turn starts with no
27
+ known window — naming the model and what is lost. Three different causes have
28
+ produced an unknown window so far, and each was reported only where it
29
+ happened, if at all.
30
+
31
+ ## 0.15.1
32
+
33
+ ### A repeat visit no longer loses the model's context window or the hub tools
34
+
35
+ The hub answers `/api/llms` and `/api/mcp_servers` with an ETag and
36
+ `must-revalidate`, so a browser revalidated them on the second page load and
37
+ got `304 Not Modified`. `Response.ok` is false for a 304, and both handlers
38
+ turned that into an empty payload.
39
+
40
+ Nothing announced it. Without the model's context window the resource budget
41
+ fell to its 8 KB floor, so a page's reference data was reported as skipped even
42
+ when it would have fitted; and tool-result truncation and oldest-result
43
+ eviction both stood down, because each returns its input unchanged when it has
44
+ no window to spend. An empty hub list meanwhile showed as "No hub-registered
45
+ tools available". It all worked on a first load and stopped on every one after,
46
+ which is why a hard reload always looked fine.
47
+
48
+ Both requests now set `cache: "no-store"`, so no conditional request is sent
49
+ and the answer always carries a body. A response that is not ok is reported in
50
+ the browser console, naming what is lost, rather than being treated as an empty
51
+ result.
52
+
53
+ The hub stopped sending those ETags as well, so this release is not required to
54
+ fix a page served by an up-to-date hub. It matters for any other server that
55
+ does send them, and for making the next failure audible.
56
+
6
57
  ## 0.15.0
7
58
 
8
59
  ### The declared global is resolved when a handler is needed, not at startup
data/README.md CHANGED
@@ -61,7 +61,7 @@ Option 3 if it does not.
61
61
 
62
62
  ```ruby
63
63
  # Gemfile
64
- gem "llm_meta_widget", "~> 0.15.0"
64
+ gem "llm_meta_widget", "~> 0.15.2"
65
65
  ```
66
66
 
67
67
  ```bash
@@ -502,9 +502,33 @@ function boot(cfg) {
502
502
  });
503
503
  if (flat.length > 1) modelPicker.style.display = "";
504
504
  }));
505
- } else if (ENABLE_MODEL_PICKER && modelPicker) {
506
- tasks.push(fetch(LLM_BASE + "/api/llms", { headers: { "Accept": "application/json" } })
507
- .then(function(r) { return r.ok ? r.json() : { llms: [] }; })
505
+ }
506
+ // The hub answers with each model's context window, and every budget below
507
+ // is derived from it, so ASK REGARDLESS OF THE PICKER. This used to sit
508
+ // inside the picker branches: a page that pinned a model and hid the
509
+ // picker — which is a sensible thing to do, and what the standalone E2E
510
+ // fixture does — never learned the window at all. The resource budget then
511
+ // fell to its 8 KB floor and both tool-result truncation and eviction stood
512
+ // down, each returning its input unchanged without a window. No warning was
513
+ // possible either, because no request was made to fail.
514
+ //
515
+ // Skipped only when talking straight to Ollama, which has no /api/llms.
516
+ if (LLM_PROVIDER !== "ollama") {
517
+ // cache: "no-store" so the browser never sends a conditional request. The
518
+ // hub answers /api/llms with an ETag and must-revalidate, so a REPEAT visit
519
+ // got 304 Not Modified — and Response.ok is false for a 304, which became
520
+ // an empty payload here. The model's context window was then unknown, so
521
+ // the resource budget fell to its 8 KB floor and BOTH tool-result
522
+ // truncation and eviction stood down, each returning unchanged without a
523
+ // window. It worked on a first load and quietly stopped on every one after.
524
+ tasks.push(fetch(LLM_BASE + "/api/llms", { headers: { "Accept": "application/json" }, cache: "no-store" })
525
+ .then(function(r) {
526
+ if (r.ok) return r.json();
527
+ console.warn("[llm-meta-widget] /api/llms answered " + r.status +
528
+ "; the model context window is unknown, so reference data is" +
529
+ " budgeted at the floor and oversized tool results are not trimmed");
530
+ return { llms: [] };
531
+ })
508
532
  .then(function(payload) {
509
533
  // /api/llms is heterogeneous per family:
510
534
  // - OpenAI/Anthropic/Google: `models: [{ name, display_name, ... }]`
@@ -515,6 +539,13 @@ function boot(cfg) {
515
539
  // configured model is often hosted while the picker shows local ones.
516
540
  llmsPayload = payload;
517
541
  modelWindow = modelWindowFrom(payload, MODEL);
542
+
543
+ // The window is the part every page needs; filling the picker is only for
544
+ // pages that show one, and the code below would dereference a null picker.
545
+ // Without this the TypeError only skips the rest of boot, whose
546
+ // remaining job is the picker's change handler — so nothing a
547
+ // no-picker page needs. Kept for intent, not for a visible bug.
548
+ if (!(ENABLE_MODEL_PICKER && modelPicker)) return;
518
549
  var flat = [];
519
550
  (payload.llms || []).forEach(function(llm) {
520
551
  if (llm.family !== "ollama") return;
@@ -551,8 +582,16 @@ function boot(cfg) {
551
582
  }
552
583
 
553
584
  if (ENABLE_TOOL_PICKER && toolsListEl) {
554
- tasks.push(fetch(TOOL_HUB_BASE + "/api/mcp_servers", { headers: { "Accept": "application/json" } })
555
- .then(function(r) { return r.ok ? r.json() : { mcp_servers: [] }; })
585
+ // Same reason as /api/llms above: a 304 on a repeat visit emptied this, and
586
+ // the panel then said "No hub-registered tools available" although the hub
587
+ // had them.
588
+ tasks.push(fetch(TOOL_HUB_BASE + "/api/mcp_servers", { headers: { "Accept": "application/json" }, cache: "no-store" })
589
+ .then(function(r) {
590
+ if (r.ok) return r.json();
591
+ console.warn("[llm-meta-widget] /api/mcp_servers answered " + r.status +
592
+ "; hub-registered tools will be listed as unavailable");
593
+ return { mcp_servers: [] };
594
+ })
556
595
  .then(function(payload) {
557
596
  hubMcpServers = (payload.mcp_servers || []).filter(function(s) {
558
597
  return anyAllowedByAllowlist(s.name, HUB_TOOLS_ALLOWLIST);
@@ -702,6 +741,7 @@ function boot(cfg) {
702
741
  // call answers, and null forever if the hub is older than the field — in
703
742
  // which case the loop budgets nothing, exactly as it always did.
704
743
  var modelWindow = null;
744
+ var warnedNoWindow = false;
705
745
  // The /api/llms answer, kept so switching model in the picker can resolve
706
746
  // that model's window. Without it a visitor who switches from a 262k model
707
747
  // to a 32k one keeps the big window — no eviction, and a resource budget
@@ -1351,6 +1391,18 @@ function boot(cfg) {
1351
1391
  inputEl.value = "";
1352
1392
  appendTurn("user", userText, pendingTurnLabel);
1353
1393
 
1394
+ // An unknown window is not a small window: every budget below then uses a
1395
+ // floor, and oversized tool results are neither trimmed nor evicted. Say so
1396
+ // once, at the moment it affects an answer. Three separate causes have led
1397
+ // here — a 304 read as empty, a page that hid the model picker, and a model
1398
+ // the hub does not list — and the first two were silent for days.
1399
+ if (!modelWindow && !warnedNoWindow) {
1400
+ warnedNoWindow = true;
1401
+ console.warn("[llm-meta-widget] no context window known for " + MODEL +
1402
+ "; reference data is budgeted at the floor and oversized tool" +
1403
+ " results are not trimmed");
1404
+ }
1405
+
1354
1406
  // Reference data that did not fit, reported once per budget, at the moment
1355
1407
  // it affects an answer rather than at boot.
1356
1408
  // Plan the page's resources first: the refusals are recorded while planning,
@@ -4269,12 +4269,16 @@ function boot(cfg) {
4269
4269
  });
4270
4270
  if (flat.length > 1) modelPicker.style.display = "";
4271
4271
  }));
4272
- } else if (ENABLE_MODEL_PICKER && modelPicker) {
4273
- tasks.push(fetch(LLM_BASE + "/api/llms", { headers: { "Accept": "application/json" } }).then(function(r) {
4274
- return r.ok ? r.json() : { llms: [] };
4272
+ }
4273
+ if (LLM_PROVIDER !== "ollama") {
4274
+ tasks.push(fetch(LLM_BASE + "/api/llms", { headers: { "Accept": "application/json" }, cache: "no-store" }).then(function(r) {
4275
+ if (r.ok) return r.json();
4276
+ console.warn("[llm-meta-widget] /api/llms answered " + r.status + "; the model context window is unknown, so reference data is budgeted at the floor and oversized tool results are not trimmed");
4277
+ return { llms: [] };
4275
4278
  }).then(function(payload) {
4276
4279
  llmsPayload = payload;
4277
4280
  modelWindow = modelWindowFrom(payload, MODEL);
4281
+ if (!(ENABLE_MODEL_PICKER && modelPicker)) return;
4278
4282
  var flat = [];
4279
4283
  (payload.llms || []).forEach(function(llm) {
4280
4284
  if (llm.family !== "ollama") return;
@@ -4304,8 +4308,10 @@ function boot(cfg) {
4304
4308
  }));
4305
4309
  }
4306
4310
  if (ENABLE_TOOL_PICKER && toolsListEl) {
4307
- tasks.push(fetch(TOOL_HUB_BASE + "/api/mcp_servers", { headers: { "Accept": "application/json" } }).then(function(r) {
4308
- return r.ok ? r.json() : { mcp_servers: [] };
4311
+ tasks.push(fetch(TOOL_HUB_BASE + "/api/mcp_servers", { headers: { "Accept": "application/json" }, cache: "no-store" }).then(function(r) {
4312
+ if (r.ok) return r.json();
4313
+ console.warn("[llm-meta-widget] /api/mcp_servers answered " + r.status + "; hub-registered tools will be listed as unavailable");
4314
+ return { mcp_servers: [] };
4309
4315
  }).then(function(payload) {
4310
4316
  hubMcpServers = (payload.mcp_servers || []).filter(function(s) {
4311
4317
  return anyAllowedByAllowlist(s.name, HUB_TOOLS_ALLOWLIST);
@@ -4421,6 +4427,7 @@ function boot(cfg) {
4421
4427
  return Object.assign({}, p, { source: "page" });
4422
4428
  });
4423
4429
  var modelWindow = null;
4430
+ var warnedNoWindow = false;
4424
4431
  var llmsPayload = null;
4425
4432
  var resourceContext = null;
4426
4433
  var resourcePlan = null;
@@ -4864,6 +4871,10 @@ function boot(cfg) {
4864
4871
  if (!userText) return;
4865
4872
  inputEl.value = "";
4866
4873
  appendTurn("user", userText, pendingTurnLabel);
4874
+ if (!modelWindow && !warnedNoWindow) {
4875
+ warnedNoWindow = true;
4876
+ console.warn("[llm-meta-widget] no context window known for " + MODEL + "; reference data is budgeted at the floor and oversized tool results are not trimmed");
4877
+ }
4867
4878
  pageResourcePlansNow();
4868
4879
  if (skippedResources.length && !announcedSkips) {
4869
4880
  announcedSkips = true;
@@ -1,3 +1,3 @@
1
1
  module LlmMetaWidget
2
- VERSION = "0.15.0"
2
+ VERSION = "0.15.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llm_meta_widget
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.15.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - jdkim