Theseus 0.3.119: LLMs out of the search dropdown; reorder by popularity; add DuckAI, Alisa, Qwen
The toolbar magnifier dropdown mixed search engines and AI chat engines in one
list, which left the Pick-AI button on the sidebar strip looking redundant and
cluttered the thing people reach for when they want to find something on the
web. The dropdown is now search-only; LLMs are picked through the strip's own
AI picker overlay (which already lists them with real icons).
LLM order follows rough global popularity so a fresh profile defaults to the
one most people reach for: ChatGPT, Gemini, Grok, Perplexity, DuckAI, Alisa,
Qwen. Three additions along with it:
* DuckAI (duck.ai) — anonymous, no sign-up, serves GPT-4o mini + Claude 3
Haiku + Llama 3 + Mistral behind one URL. Also wired as a toolbar search
target with pre-filled answer via &ia=chat.
* Alisa (ya.ru/alisa) — Russian-language assistant from Yandex.
* Qwen (chat.qwen.ai) — Alibaba's Tongyi chat; email sign-up, the strongest
non-mainland-phone access to a Chinese model.
Phind stays frozen (Vercel 404 at the root). A saved defaultLlmId pointing at
a frozen engine is cleared so the fallback resolves to the new list[0] rather
than silently flipping to whatever was second.
Engine home URLs can now opt into an override via a `home` field — needed by
DuckAI (its chat lives at the apex of duck.ai but prefers that URL over the
duckduckgo.com stem) and Alisa (chat UI lives at /alisa, not the apex of
ya.ru).
This commit is contained in:
parent
61c605a97f
commit
47a739ad72
5 changed files with 65 additions and 23 deletions
1
engine-icons/alisa.svg
Normal file
1
engine-icons/alisa.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Alisa"><rect width="64" height="64" rx="14" fill="#7c4dff"/><text x="32" y="42" text-anchor="middle" font-family="system-ui,-apple-system,sans-serif" font-weight="800" font-size="34" fill="#ffffff">A</text></svg>
|
||||
|
After Width: | Height: | Size: 296 B |
1
engine-icons/duckai.svg
Normal file
1
engine-icons/duckai.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="DuckDuckGo AI"><rect width="64" height="64" rx="14" fill="#de5833"/><text x="32" y="42" text-anchor="middle" font-family="system-ui,-apple-system,sans-serif" font-weight="800" font-size="34" fill="#ffffff">D</text></svg>
|
||||
|
After Width: | Height: | Size: 304 B |
1
engine-icons/qwen.svg
Normal file
1
engine-icons/qwen.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Qwen"><rect width="64" height="64" rx="14" fill="#6b4bff"/><text x="32" y="42" text-anchor="middle" font-family="system-ui,-apple-system,sans-serif" font-weight="800" font-size="34" fill="#ffffff">Q</text></svg>
|
||||
|
After Width: | Height: | Size: 295 B |
83
main.js
83
main.js
|
|
@ -153,19 +153,37 @@ const SEARCH_ENGINES = {
|
|||
// default becomes stale as instances rate-limit / die (searx.be is anti-bot-locked).
|
||||
// Users who want SearXNG add their preferred instance via the custom URL form.
|
||||
wikipedia: { kind: "search", tier: "catalog", name: "Wikipedia", sym: "📖", fav: "en.wikipedia.org", url: (q) => "https://en.wikipedia.org/wiki/Special:Search?search=" + encodeURIComponent(q) },
|
||||
// AI / LLM answer engines. The first group answers a URL query without any
|
||||
// login, so they also work as a "search engine" in the toolbar. The second
|
||||
// group needs an account (free tier) and bounces ?q= to the sign-in gate —
|
||||
// they're useful as sidebar LLM targets (opens the chat home) but not as
|
||||
// the toolbar default search; set one of the first group there instead.
|
||||
perplexity: { kind: "llm", tier: "catalog", name: "Perplexity", sym: "🧠", fav: "www.perplexity.ai", url: (q) => "https://www.perplexity.ai/search?q=" + encodeURIComponent(q) },
|
||||
phind: { kind: "llm", tier: "catalog", name: "Phind", sym: "🧑💻", fav: "www.phind.com", frozen: "Phind's web UI returns a Vercel 404 at the root (2026-10-27).", url: (q) => "https://www.phind.com/search?q=" + encodeURIComponent(q) },
|
||||
// Account-gated LLMs — free tier available on all three. ChatGPT and Grok
|
||||
// accept ?q=<query> on their home URL and pre-fill the composer; Gemini's
|
||||
// webapp ignores query strings so it just lands on the chat screen.
|
||||
// AI / LLM answer engines, ordered by rough global popularity so the first
|
||||
// entry is a sensible default for a new profile. `home` overrides the
|
||||
// llmHomeUrl calculation when the chat UI lives on a path, not the apex.
|
||||
// Perplexity + DuckAI answer a URL query without any login, so they also
|
||||
// work as a toolbar search engine; the rest open their chat home.
|
||||
//
|
||||
// We used to list these engines in the toolbar search dropdown too, but as
|
||||
// of 0.3.119 that dropdown is search-only — the Pick AI button in the
|
||||
// sidebar strip is where you choose which LLM to launch, and emitEngines()
|
||||
// filters LLMs out of what the toolbar engine picker sees. See the comment
|
||||
// on emitEngines() for the invariant.
|
||||
chatgpt: { kind: "llm", tier: "catalog", name: "ChatGPT", sym: "💬", fav: "chatgpt.com", url: (q) => "https://chatgpt.com/?q=" + encodeURIComponent(q) },
|
||||
grok: { kind: "llm", tier: "catalog", name: "Grok", sym: "🪐", fav: "grok.com", url: (q) => "https://grok.com/?q=" + encodeURIComponent(q) },
|
||||
gemini: { kind: "llm", tier: "catalog", name: "Gemini", sym: "✦", fav: "gemini.google.com", url: (q) => "https://gemini.google.com/app?q=" + encodeURIComponent(q) },
|
||||
grok: { kind: "llm", tier: "catalog", name: "Grok", sym: "🪐", fav: "grok.com", url: (q) => "https://grok.com/?q=" + encodeURIComponent(q) },
|
||||
perplexity: { kind: "llm", tier: "catalog", name: "Perplexity", sym: "🧠", fav: "www.perplexity.ai", url: (q) => "https://www.perplexity.ai/search?q=" + encodeURIComponent(q) },
|
||||
// DuckDuckGo AI Chat — no sign-up, anonymous: GPT-4o mini + Claude 3 Haiku +
|
||||
// Llama 3 + Mistral behind one URL. Serves ?q= on the regular DDG host and
|
||||
// flips into the chat UI with &ia=chat, so it also doubles as a toolbar
|
||||
// search target with pre-filled answer.
|
||||
duckai: { kind: "llm", tier: "catalog", name: "DuckDuckGo AI", sym: "🦆", fav: "duck.ai", home: "https://duck.ai/", url: (q) => "https://duckduckgo.com/?q=" + encodeURIComponent(q) + "&ia=chat" },
|
||||
// Yandex Alisa — Russian-language chatbot. The chat UI is on a path, so we
|
||||
// route home via `home`; URL-query mode falls back to regular Yandex search
|
||||
// (ya.ru does not expose a public URL to open the chat with a pre-filled
|
||||
// prompt).
|
||||
alisa: { kind: "llm", tier: "catalog", name: "Alisa", sym: "🇷🇺", fav: "ya.ru", home: "https://ya.ru/alisa", url: (q) => "https://ya.ru/?text=" + encodeURIComponent(q) },
|
||||
// Qwen chat — Alibaba's Tongyi Qianwen chat; email sign-up (no phone), the
|
||||
// strongest open-weights Chinese model that is reachable without a mainland
|
||||
// phone number. Query strings are ignored by the composer, so URL-query mode
|
||||
// just lands on the chat home.
|
||||
qwen: { kind: "llm", tier: "catalog", name: "Qwen", sym: "通", fav: "chat.qwen.ai", url: (q) => "https://chat.qwen.ai/?q=" + encodeURIComponent(q) },
|
||||
phind: { kind: "llm", tier: "catalog", name: "Phind", sym: "🧑💻", fav: "www.phind.com", frozen: "Phind's web UI returns a Vercel 404 at the root (2026-10-27).", url: (q) => "https://www.phind.com/search?q=" + encodeURIComponent(q) },
|
||||
// ---- Extras: wider bank, discoverable via the Search filter box in Settings.
|
||||
// These are known-working engines that don't require sign-in on ?q= but aren't
|
||||
// first-class enough to sit in the primary catalog. Keep the list vetted — if
|
||||
|
|
@ -182,7 +200,7 @@ const SEARCH_ENGINES = {
|
|||
};
|
||||
// Engines enabled by default (shown in the toolbar dropdown). The rest are in the
|
||||
// catalog and can be turned on from Settings. Custom + detected engines are always on.
|
||||
const DEFAULT_ENABLED = ["startpage", "duckduckgo", "google", "brave", "bing", "perplexity", "chatgpt", "grok", "gemini"]; // Phind removed 2026-10-27 — frozen (Vercel 404 at root)
|
||||
const DEFAULT_ENABLED = ["startpage", "duckduckgo", "google", "brave", "bing", "chatgpt", "gemini", "grok", "perplexity", "duckai", "alisa", "qwen"]; // LLM order 2026-10-27 by popularity; Phind frozen (Vercel 404 at root)
|
||||
// A frozen catalog engine (`frozen: "<reason>"`) stays visible in Settings so the user sees why it
|
||||
// is gone, but it is never enabled, never offered in the picker and never the default. Unfreeze by
|
||||
// deleting the field; the user's installed list is left alone, so the row comes back as it was.
|
||||
|
|
@ -317,9 +335,11 @@ function enabledEnginesList() { return allEngines().filter((e) => e.enabled); }
|
|||
// and the "Pick…" menu lists everything here.
|
||||
function enabledLlms() { return enabledEnginesList().filter((e) => e.kind === "llm"); }
|
||||
// A home URL for an LLM engine so we can open its web UI in the panel.
|
||||
// Each engine's `fav` field is the hostname; the home page is the root.
|
||||
// `home` overrides when the chat UI lives on a path (duck.ai, ya.ru/alisa);
|
||||
// otherwise each engine's `fav` field is the hostname and the home is its root.
|
||||
function llmHomeUrl(engineId) {
|
||||
const def = SEARCH_ENGINES[engineId];
|
||||
if (def && def.home) return def.home;
|
||||
if (def && def.fav) return "https://" + def.fav + "/";
|
||||
// Custom engines fall back to the origin of their URL template.
|
||||
const custom = (settings.customEngines || []).find((e) => e.id === engineId);
|
||||
|
|
@ -741,13 +761,17 @@ function loadSettings() {
|
|||
settings.searchEngine = enabled.find((x) => !isFrozen(x)) || DEFAULT_ENABLED[0];
|
||||
}
|
||||
} catch (e) { console.warn("engine normalize:", e?.message); }
|
||||
// One-time LLM-engine offer (0.3.101): three new account-gated LLMs were
|
||||
// added to DEFAULT_ENABLED, but an existing profile's enabledEngines is
|
||||
// already set so the fresh default doesn't take effect. Add each one the
|
||||
// first time this upgrade runs; `enginesOffered` remembers it so a user
|
||||
// who disables one keeps it disabled across restarts.
|
||||
// One-time LLM-engine offer: new engines ride on top of DEFAULT_ENABLED but an
|
||||
// existing profile's enabledEngines is already set, so a fresh default alone
|
||||
// never takes effect. Each id appears here once; `enginesOffered` remembers
|
||||
// every offer so a user who disables one keeps it disabled across restarts,
|
||||
// and so adding another engine next release won't re-offer the old ones.
|
||||
// • 0.3.101 — chatgpt, grok, gemini
|
||||
// • 0.3.119 — duckai (anonymous, no sign-up), alisa (Yandex),
|
||||
// qwen (Alibaba, email sign-up — strongest non-mainland-phone
|
||||
// access to a Chinese LLM)
|
||||
try {
|
||||
const OFFER = ["chatgpt", "grok", "gemini"];
|
||||
const OFFER = ["chatgpt", "grok", "gemini", "duckai", "alisa", "qwen"];
|
||||
const offered = Array.isArray(settings.enginesOffered) ? settings.enginesOffered.slice() : [];
|
||||
let changed = false;
|
||||
for (const id of OFFER) {
|
||||
|
|
@ -758,6 +782,14 @@ function loadSettings() {
|
|||
}
|
||||
if (changed) settings.enginesOffered = offered;
|
||||
} catch (e) { console.warn("engines offer:", e?.message); }
|
||||
// Phind was marked frozen in 0.3.118 (its Vercel 404s), so if the user's
|
||||
// saved default LLM was phind the sidebar strip falls through to list[0] —
|
||||
// which, under the pre-0.3.119 ordering, happened to be Perplexity. The
|
||||
// 0.3.119 reorder puts ChatGPT at list[0] instead, so clearing the stale
|
||||
// pointer makes the fallback resolve to ChatGPT (currently the single most
|
||||
// popular chat UI) rather than silently flipping their choice.
|
||||
try { if (settings.defaultLlmId && isFrozen(settings.defaultLlmId)) settings.defaultLlmId = null; }
|
||||
catch (e) { console.warn("defaultLlmId migrate:", e?.message); }
|
||||
// Quick-links default set changed in 0.3.70: drop Messenger + Spotify and
|
||||
// reorder to Telegram, WhatsApp, X, YouTube. Users who kept the previous
|
||||
// untouched default (same 6 ids, same order) move to the new set; any
|
||||
|
|
@ -1372,9 +1404,16 @@ small{color:#b98b92}code{font:12px ui-monospace,monospace;word-break:break-all}<
|
|||
<p><small>To decide for yourself, type <b>${esc(host)}</b> in the address bar: Theseus shows the full warning there, with the option to continue where one exists.</small></p></div></body></html>`;
|
||||
}
|
||||
|
||||
// INVARIANT: the toolbar's engine picker is search-only — LLMs are picked
|
||||
// through the sidebar strip's Pick AI overlay (llm-picker.html), which reads
|
||||
// enabledLlms() through llmPickerState(), not this payload. Keep LLMs out of
|
||||
// what the toolbar sees so the dropdown stays focused on finding things on
|
||||
// the web; Settings still gets the full list via `search-engines` IPC.
|
||||
function searchDropdownEngines() { return enabledEnginesList().filter((e) => (e.kind || "search") !== "llm"); }
|
||||
function emitEngines() {
|
||||
sendAllChrome("engines", { engines: enabledEnginesList(), current: settings.searchEngine });
|
||||
if (epVisible) try { enginePicker?.webContents.send("engines", { engines: enabledEnginesList(), current: settings.searchEngine, detected: activeTab()?.detected || null }); } catch {}
|
||||
const engines = searchDropdownEngines();
|
||||
sendAllChrome("engines", { engines, current: settings.searchEngine });
|
||||
if (epVisible) try { enginePicker?.webContents.send("engines", { engines, current: settings.searchEngine, detected: activeTab()?.detected || null }); } catch {}
|
||||
}
|
||||
// WebRTC IP-handling policy — the same control the "WebRTC Network Limiter"
|
||||
// Chrome extension provides, done natively (that extension's chrome.privacy API
|
||||
|
|
@ -4291,7 +4330,7 @@ function showEnginePicker(show) {
|
|||
raise(enginePicker);
|
||||
enginePicker.setVisible(true); epVisible = true;
|
||||
if (win.isFocused()) try { enginePicker.webContents.focus(); } catch {} // see closeOnClickAway
|
||||
enginePicker.webContents.send("engines", { engines: enabledEnginesList(), current: settings.searchEngine, detected: activeTab()?.detected || null });
|
||||
enginePicker.webContents.send("engines", { engines: searchDropdownEngines(), current: settings.searchEngine, detected: activeTab()?.detected || null });
|
||||
} else { cancelOverlayShow(enginePicker); enginePicker.setVisible(false); epVisible = false; }
|
||||
}
|
||||
// Floating language picker — same shape as the engine picker above. The
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "theseus-navigator",
|
||||
"version": "0.3.118",
|
||||
"version": "0.3.119",
|
||||
"license": "MPL-2.0",
|
||||
"description": "Theseus Navigator — a browser that follows the thread. By Silent Mode, a Deviant project.",
|
||||
"author": "Silent Mode",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue