termsearch 0.3.5 → 0.3.7

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/bin/termsearch.js CHANGED
@@ -376,7 +376,7 @@ async function cmdAutostart(sub) {
376
376
  async function cmdDefault(flags) {
377
377
  const { running, pid } = getStatus();
378
378
  if (running) {
379
- cmdStatus();
379
+ await cmdStatus();
380
380
  } else {
381
381
  await cmdStart(flags);
382
382
  if (getStatus().running) {
@@ -208,6 +208,7 @@ function svg(paths, size = 16, extra = '') {
208
208
 
209
209
  const ICONS = {
210
210
  search: svg('<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>'),
211
+ filter: svg('<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>'),
211
212
  settings: svg('<circle cx="12" cy="12" r="3"/><path d="M12 2v3m0 14v3M2 12h3m14 0h3m-3.7-8.3-2.1 2.1m-8.4 8.4-2.1 2.1m12.5 0-2.1-2.1M5.7 5.7 3.6 3.6"/>'),
212
213
  theme: svg('<circle cx="12" cy="12" r="5"/><path d="M12 1v2m0 18v2M4.22 4.22l1.42 1.42m12.72 12.72 1.42 1.42M1 12h2m18 0h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>'),
213
214
  back: svg('<path d="M19 12H5"/><path d="m12 5-7 7 7 7"/>'),
@@ -267,6 +268,7 @@ const AI_PRESETS = [
267
268
  { id: 'chutes', label: 'Chutes.ai TEE', api_base: 'https://llm.chutes.ai/v1', keyRequired: true, defaultModel: 'deepseek-ai/DeepSeek-V3.2-TEE' },
268
269
  { id: 'anthropic',label: 'Anthropic', api_base: 'https://api.anthropic.com/v1', keyRequired: true, defaultModel: 'claude-3-5-haiku-latest' },
269
270
  { id: 'openai', label: 'OpenAI', api_base: 'https://api.openai.com/v1', keyRequired: true, defaultModel: 'gpt-4o-mini' },
271
+ { id: 'openrouter', label: 'OpenRoute/OpenRouter', api_base: 'https://openrouter.ai/api/v1', keyRequired: true, defaultModel: 'openai/gpt-4o-mini' },
270
272
  ];
271
273
 
272
274
  const ENGINE_GROUPS = [
@@ -313,13 +315,19 @@ function LangPicker() {
313
315
  return wrap;
314
316
  }
315
317
 
316
- function EnginePicker() {
317
- const details = el('details', { className: 'engine-picker' });
318
+ function EnginePicker(opts = {}) {
319
+ const compact = Boolean(opts.compact);
320
+ const details = el('details', { className: `engine-picker${compact ? ' engine-picker-compact' : ''}` });
318
321
  const selectedCount = state.selectedEngines.length;
319
- const summary = el('summary', { className: 'engine-picker-summary' },
320
- el('span', { className: 'engine-picker-title' }, selectedCount ? `Engines (${selectedCount})` : 'Engines (all)'),
321
- iconEl('chevron', 'engine-chevron'),
322
- );
322
+ const summary = compact
323
+ ? el('summary', { className: 'engine-picker-summary engine-picker-summary-icon', title: 'Search engines' },
324
+ iconEl('filter', 'engine-filter-icon'),
325
+ selectedCount ? el('span', { className: 'engine-picker-count' }, String(selectedCount)) : null,
326
+ )
327
+ : el('summary', { className: 'engine-picker-summary' },
328
+ el('span', { className: 'engine-picker-title' }, selectedCount ? `Engines (${selectedCount})` : 'Engines (all)'),
329
+ iconEl('chevron', 'engine-chevron'),
330
+ );
323
331
 
324
332
  const body = el('div', { className: 'engine-picker-body' });
325
333
  const presetRow = el('div', { className: 'engine-preset-row' });
@@ -1020,6 +1028,7 @@ function renderApp() {
1020
1028
  el('div', { className: 'header-search' }, SearchForm(state.query, (q, cat) => { state.query = q; doSearch(q, cat); })),
1021
1029
  el('div', { className: 'header-nav' },
1022
1030
  LangPicker(),
1031
+ EnginePicker({ compact: true }),
1023
1032
  el('button', { className: 'btn-icon', title: 'Settings', onClick: () => navigate('#/settings') }, iconEl('settings')),
1024
1033
  el('button', { className: 'btn-icon', title: 'Toggle theme', onClick: toggleTheme }, iconEl('theme')),
1025
1034
  ),
@@ -1046,7 +1055,6 @@ function renderApp() {
1046
1055
  });
1047
1056
  };
1048
1057
  buildCatTabs(categoryBar);
1049
- categoryBar.append(EnginePicker());
1050
1058
 
1051
1059
  const mobileTabs = el('div', { className: 'mobile-bar-tabs' });
1052
1060
  buildCatTabs(mobileTabs);
@@ -1058,8 +1066,8 @@ function renderApp() {
1058
1066
  className: 'mobile-logo',
1059
1067
  onClick: () => { state.query = ''; state.category = 'web'; navigate('#/'); renderApp(); },
1060
1068
  }, 'Term', el('strong', {}, 'Search')),
1061
- EnginePicker(),
1062
1069
  LangPicker(),
1070
+ EnginePicker({ compact: true }),
1063
1071
  el('button', { className: 'btn-icon', title: 'Settings', onClick: () => navigate('#/settings') }, iconEl('settings')),
1064
1072
  el('button', { className: 'btn-icon', title: 'Toggle theme', onClick: toggleTheme }, iconEl('theme')),
1065
1073
  ),
@@ -1475,7 +1483,7 @@ async function renderSettings() {
1475
1483
  el('label', { className: 'form-label', for: 'ai-base' }, 'API Endpoint'),
1476
1484
  makeInput('ai-base', ai.api_base, 'http://localhost:11434/v1'),
1477
1485
  el('div', { className: 'form-hint' },
1478
- 'Included presets: LocalHost (Ollama · LM Studio · llama.cpp) · Chutes.ai TEE · Anthropic · OpenAI',
1486
+ 'Included presets: LocalHost (Ollama · LM Studio · llama.cpp) · Chutes.ai TEE · Anthropic · OpenAI · OpenRoute/OpenRouter',
1479
1487
  el('br', {}),
1480
1488
  'You can also keep custom OpenAI-compatible endpoints.',
1481
1489
  ),
@@ -161,7 +161,6 @@ a:hover { color: var(--link-h); }
161
161
  }
162
162
 
163
163
  .engine-picker {
164
- margin-left: auto;
165
164
  position: relative;
166
165
  }
167
166
  .engine-picker summary {
@@ -182,6 +181,43 @@ a:hover { color: var(--link-h); }
182
181
  font-size: 11px;
183
182
  cursor: pointer;
184
183
  }
184
+ .engine-picker-summary-icon {
185
+ width: 32px;
186
+ height: 32px;
187
+ padding: 0;
188
+ border-radius: var(--radius-sm);
189
+ justify-content: center;
190
+ background: transparent;
191
+ color: var(--text3);
192
+ border-color: var(--border);
193
+ position: relative;
194
+ }
195
+ .engine-picker-summary-icon:hover {
196
+ border-color: #3a3a3a;
197
+ color: var(--text2);
198
+ }
199
+ .engine-filter-icon {
200
+ display: inline-flex;
201
+ align-items: center;
202
+ }
203
+ .engine-picker-count {
204
+ position: absolute;
205
+ top: -5px;
206
+ right: -5px;
207
+ min-width: 14px;
208
+ height: 14px;
209
+ border-radius: 999px;
210
+ padding: 0 3px;
211
+ display: inline-flex;
212
+ align-items: center;
213
+ justify-content: center;
214
+ background: rgba(109,40,217,0.95);
215
+ color: #fff;
216
+ border: 1px solid rgba(167,139,250,0.55);
217
+ font-size: 9px;
218
+ font-weight: 700;
219
+ line-height: 1;
220
+ }
185
221
  .engine-picker-title {
186
222
  white-space: nowrap;
187
223
  }
@@ -968,7 +1004,6 @@ a:hover { color: var(--link-h); }
968
1004
  gap: 6px;
969
1005
  padding: 4px 12px 2px;
970
1006
  }
971
- .mobile-bar-row .engine-picker { flex-shrink: 0; }
972
1007
  .mobile-bar-row .lang-wrap { margin-left: auto; }
973
1008
 
974
1009
  /* ─── Responsive ──────────────────────────────────────────────────────────── */
@@ -978,8 +1013,17 @@ a:hover { color: var(--link-h); }
978
1013
  .main { padding-bottom: calc(20px + var(--mobile-bar-height, 0px) + env(safe-area-inset-bottom, 0px)); }
979
1014
 
980
1015
  .cat-tab { font-size: 10px; padding: 4px 8px; }
981
- .mobile-bar-row .engine-picker-summary { font-size: 11px; padding: 3px 6px; }
982
- .engine-picker-body { width: calc(100vw - 24px); right: -6px; bottom: calc(100% + 8px); top: auto; }
1016
+ .mobile-bar-row .engine-picker-summary-icon { width: 30px; height: 30px; }
1017
+ .engine-picker-body {
1018
+ position: fixed;
1019
+ left: 10px;
1020
+ right: 10px;
1021
+ width: auto;
1022
+ max-height: min(62vh, 520px);
1023
+ bottom: calc(var(--mobile-bar-height, 0px) + env(safe-area-inset-bottom, 0px) + 10px);
1024
+ top: auto;
1025
+ z-index: 260;
1026
+ }
983
1027
  .logo-text { font-size: 15px; }
984
1028
  .home-logo { font-size: 40px; }
985
1029
  .home-tagline { letter-spacing: 0.08em; margin-bottom: 20px; }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "termsearch",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Personal search engine for Termux/Linux/macOS — zero-config, privacy-first, AI-optional",
5
5
  "type": "module",
6
6
  "bin": {
7
- "termsearch": "./bin/termsearch.js"
7
+ "termsearch": "bin/termsearch.js"
8
8
  },
9
9
  "main": "./src/server.js",
10
10
  "files": [
@@ -43,6 +43,6 @@
43
43
  "license": "MIT",
44
44
  "repository": {
45
45
  "type": "git",
46
- "url": "https://github.com/DioNanos/termsearch"
46
+ "url": "git+https://github.com/DioNanos/termsearch.git"
47
47
  }
48
48
  }