@symerian/symi 3.5.12 → 3.5.13

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.5.12",
3
- "commit": "ba937470adc8cb729ea183e67afa9e9b23fa2245",
4
- "builtAt": "2026-05-06T02:37:25.750Z"
2
+ "version": "3.5.13",
3
+ "commit": "33e6d6051e6f74ada770ca1941c409ce7ba65cd2",
4
+ "builtAt": "2026-05-06T02:46:17.820Z"
5
5
  }
@@ -1 +1 @@
1
- 74ed545b32825cef7fb4fa2f000acd88a717aaea0e2acf93d7d7c1b8ed2be576
1
+ b6b358862b350355c1027203e25ea1b0380203d1ceff6fb6a17ee5d3259e905e
@@ -397,57 +397,59 @@ body {
397
397
  letter-spacing: 0.05em;
398
398
  }
399
399
 
400
- /* ── Model Routing list ────────────────────────────────────────────── */
401
- .model-routing-list {
402
- display: flex;
403
- flex-direction: column;
404
- gap: 10px;
405
- margin-bottom: 8px;
406
- }
407
- .model-section {
408
- display: flex;
409
- flex-direction: column;
410
- gap: 3px;
411
- }
412
- .model-section-header {
413
- font-family: var(--font-mono);
414
- font-size: 9px;
415
- letter-spacing: 0.08em;
416
- text-transform: uppercase;
417
- color: var(--text-dim);
418
- opacity: 0.6;
419
- padding: 0 2px 2px;
420
- border-bottom: 1px solid rgba(255, 255, 255, 0.06);
421
- margin-bottom: 2px;
422
- }
423
- .model-item {
400
+ /* ── Model Routing select ──────────────────────────────────────────── */
401
+ .model-routing-select {
424
402
  width: 100%;
425
403
  display: block;
426
- text-align: left;
427
- padding: 6px 8px;
404
+ padding: 8px 22px 8px 8px;
405
+ margin-bottom: 6px;
428
406
  border: 1px solid var(--glass-border);
429
- border-radius: 5px;
407
+ border-radius: 6px;
430
408
  background: rgba(255, 255, 255, 0.03);
431
- color: var(--text-dim);
409
+ color: var(--text);
432
410
  font-family: var(--font-mono);
433
411
  font-size: 10px;
434
- letter-spacing: 0.03em;
435
- line-height: 1.3;
412
+ letter-spacing: 0.04em;
436
413
  cursor: pointer;
437
- transition: all 0.15s ease;
438
- white-space: normal;
439
- word-break: break-word;
414
+ transition: all 0.2s ease;
415
+ appearance: none;
416
+ -webkit-appearance: none;
417
+ background-image:
418
+ linear-gradient(45deg, transparent 50%, currentColor 50%),
419
+ linear-gradient(135deg, currentColor 50%, transparent 50%);
420
+ background-position:
421
+ calc(100% - 10px) 50%,
422
+ calc(100% - 6px) 50%;
423
+ background-size:
424
+ 4px 4px,
425
+ 4px 4px;
426
+ background-repeat: no-repeat;
427
+ text-overflow: ellipsis;
428
+ overflow: hidden;
440
429
  }
441
- .model-item:hover {
430
+ .model-routing-select:hover {
442
431
  border-color: var(--accent-cyan);
443
432
  color: var(--text);
444
433
  }
445
- .model-item.active {
446
- background: rgba(0, 212, 255, 0.08);
434
+ .model-routing-select:focus {
435
+ outline: none;
447
436
  border-color: var(--accent-cyan);
448
- color: var(--accent-cyan);
449
437
  box-shadow: 0 0 8px rgba(0, 212, 255, 0.12);
450
438
  }
439
+ .model-routing-select option {
440
+ background: #0a0a0a;
441
+ color: var(--text);
442
+ padding: 4px 0;
443
+ }
444
+ .model-routing-select optgroup {
445
+ background: #0a0a0a;
446
+ color: var(--accent-cyan);
447
+ font-style: normal;
448
+ font-weight: 600;
449
+ letter-spacing: 0.08em;
450
+ text-transform: uppercase;
451
+ font-size: 10px;
452
+ }
451
453
  .model-status {
452
454
  font-size: 10px;
453
455
  color: var(--text-dim);
@@ -120,41 +120,23 @@
120
120
 
121
121
  <div class="glass-panel" id="model-routing-panel">
122
122
  <div class="panel-label">MODEL ROUTING</div>
123
- <div class="model-routing-list" id="model-toggle">
124
- <div class="model-section">
125
- <div class="model-section-header">SPIDER</div>
126
- <button class="model-item" data-group="spider" data-value="spider-gemma4">
127
- Gemma 4 31B Uncensored
128
- </button>
129
- <button class="model-item" data-group="spider" data-value="spider-qwen35">
130
- Qwen 3.5 35B
131
- </button>
132
- <button class="model-item" data-group="spider" data-value="spider-qwen35-uncen">
133
- Qwen 3.5 Uncensored
134
- </button>
135
- <button class="model-item" data-group="spider" data-value="spider-qwen36">
136
- Qwen 3.6 35B
137
- </button>
138
- </div>
139
- <div class="model-section">
140
- <div class="model-section-header">COREWEAVE</div>
141
- <button class="model-item" data-group="coreweave" data-value="coreweave1">
142
- CoreWeave 1 (Qwen 3.5 35B)
143
- </button>
144
- <button class="model-item" data-group="coreweave" data-value="coreweave2">
145
- CoreWeave 2 (Qwen 3.6 35B)
146
- </button>
147
- <button class="model-item" data-group="coreweave" data-value="coreweave3">
148
- CoreWeave 3 (Qwen 3.6 27B)
149
- </button>
150
- </div>
151
- <div class="model-section">
152
- <div class="model-section-header">API</div>
153
- <button class="model-item" data-group="api" data-value="api">
154
- Anthropic Claude Sonnet 4.6
155
- </button>
156
- </div>
157
- </div>
123
+ <select class="model-routing-select" id="model-toggle">
124
+ <option value="" disabled selected>Select model…</option>
125
+ <optgroup label="SPIDER">
126
+ <option value="spider-gemma4">Gemma 4 31B Uncensored</option>
127
+ <option value="spider-qwen35">Qwen 3.5 35B</option>
128
+ <option value="spider-qwen35-uncen">Qwen 3.5 Uncensored</option>
129
+ <option value="spider-qwen36">Qwen 3.6 35B</option>
130
+ </optgroup>
131
+ <optgroup label="COREWEAVE">
132
+ <option value="coreweave1">CoreWeave 1 (Qwen 3.5 35B)</option>
133
+ <option value="coreweave2">CoreWeave 2 (Qwen 3.6 35B)</option>
134
+ <option value="coreweave3">CoreWeave 3 (Qwen 3.6 27B)</option>
135
+ </optgroup>
136
+ <optgroup label="API">
137
+ <option value="api">Anthropic Claude Sonnet 4.6</option>
138
+ </optgroup>
139
+ </select>
158
140
  <div class="model-status" id="model-status">loading…</div>
159
141
  </div>
160
142
 
@@ -1,15 +1,13 @@
1
- // ── Model Routing list ───────────────────────────────────────────────
2
- // Vertical sectioned list (SPIDER / COREWEAVE / API) — each .model-item
3
- // row is a click target that switches `agents.defaults.model.primary`
4
- // via config.patch. Replaced the side-by-side dropdowns + button design
5
- // in 3.5.12 because the three controls were forcing horizontal scroll
6
- // inside the panel; sectioned vertical layout has no width constraint
7
- // and lets long model names wrap naturally.
1
+ // ── Model Routing select ─────────────────────────────────────────────
2
+ // Single <select> with three <optgroup>s (SPIDER / COREWEAVE / API).
3
+ // Picking an option switches `agents.defaults.model.primary` via
4
+ // config.patch. Compact one-row presentation no horizontal scroll,
5
+ // no vertical bloat from listing every option in the panel.
8
6
 
9
7
  (function () {
10
- // data-value (per-item) → fully-qualified model id understood by the
11
- // gateway (provider/model split on first "/"; later slashes survive
12
- // and are part of the model id, e.g. for HuggingFace paths).
8
+ // <option value> → fully-qualified model id understood by the gateway
9
+ // (provider/model split on first "/"; later slashes survive and are
10
+ // part of the model id, e.g. for HuggingFace paths).
13
11
  const MODEL_IDS = {
14
12
  // SPIDER
15
13
  "spider-gemma4": "spider-gemma4/TrevorJS/gemma-4-31B-it-uncensored",
@@ -25,27 +23,29 @@
25
23
  api: "anthropic/claude-sonnet-4-6",
26
24
  };
27
25
 
28
- // Reverse: model id → data-value (for setActive lookup).
26
+ // Reverse: model id → option value (for setActive lookup).
29
27
  const idToValue = {};
30
28
  for (const [value, id] of Object.entries(MODEL_IDS)) {
31
29
  idToValue[id] = value;
32
30
  }
33
31
 
34
- const list = document.getElementById("model-toggle");
35
- const items = list ? list.querySelectorAll(".model-item") : [];
32
+ const select = document.getElementById("model-toggle");
36
33
  const statusEl = document.getElementById("model-status");
37
34
 
38
- if (!list || items.length === 0) {
35
+ if (!select) {
39
36
  return;
40
37
  }
41
38
 
42
39
  let currentHash = null;
43
40
 
44
41
  function setActive(primaryId) {
45
- const activeValue = idToValue[primaryId];
46
- items.forEach((item) => {
47
- item.classList.toggle("active", item.dataset.value === activeValue);
48
- });
42
+ const value = idToValue[primaryId];
43
+ if (value) {
44
+ select.value = value;
45
+ } else {
46
+ // Unknown model id — leave the placeholder visible.
47
+ select.value = "";
48
+ }
49
49
  }
50
50
 
51
51
  async function init() {
@@ -104,14 +104,8 @@
104
104
  }
105
105
  });
106
106
 
107
- // Single delegated click on the list → look up data-value → switch.
108
- list.addEventListener("click", (e) => {
109
- const item = e.target.closest(".model-item");
110
- if (!item) {
111
- return;
112
- }
113
- const value = item.dataset.value;
114
- const id = MODEL_IDS[value];
107
+ select.addEventListener("change", () => {
108
+ const id = MODEL_IDS[select.value];
115
109
  if (id) {
116
110
  void switchToModelId(id);
117
111
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symerian/symi",
3
- "version": "3.5.12",
3
+ "version": "3.5.13",
4
4
  "description": "Multi-channel AI gateway with extensible messaging integrations",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/jaysteelmind/symi#readme",