Commit graph

258 commits

Author SHA1 Message Date
Hermes Dev
baf86fc5a6 Claude connector: reach add-on sidebar panels (Aegis, Hermes, Pithos, …)
The connector only drove web pages. Add-on sidebar panels — Aegis's
wallet, Hermes's messenger, Pithos's storage panel, anything with
a sidebar-panel capability — were walled off: list_tabs skipped them
and webContents() refused anything that was not kind:"web".

Panels are now first-class tabs with a negative id, kind:"panel", and
an addon/panelId pair. Each open panel is listed next to the real
tabs; a closed one is still listed so a client can see what exists.
screenshot / snapshot / read_page_text / click / type / press_key /
paste_html / paste_text / wait_for / upload_file / evaluate all work
on them with the same TabDriver a web page uses. navigate /
activate_tab / close_tab refuse panels — the user owns panel
visibility, not the connector.

Approval is per add-on under a synthetic theseus-panel://<addon>
origin, so Aegis is approved once and every Aegis panel is reachable
from then on. The approval modal titles itself "Let Claude control
the Aegis panel?" when the origin is a panel origin, and the body
explains the panel is read, not the whole browser profile. Origin
pinning is skipped (the panel is served from the add-on scheme and
never navigates under us); password-field refusal and the action log
still apply, so a PIN input in a wallet panel is never typed into
and every call is in the connector's log.
2026-10-29 00:06:51 +02:00
Local Dev
1457de96b8 Claude connector: the left sidebar's web app (Telegram, WhatsApp, X, the AI chat) is tab 0
The quick-link panel is one WebContentsView outside `tabs`, so the
connector could not see a web app opened in the sidebar, and the
signed-in session there (Telegram's channel account, for one) was out of
reach. tabControl.list() now ends with the panel as tab 0 while it holds a
web page, tagged with the app's name; webContents, navigate, close and
activate handle it (activate reopens the panel, close closes it). It runs
the same preload as a web tab and still needs the site approved, so it
hands out nothing a tab doesn't. Listed last so it is never picked as the
active tab when a tool call omits tab_id.
2026-10-28 21:45:14 +02:00
Local Dev
4e3fc4bb3d Theseus 0.3.127: System section tightens — direct Ariadne, master N&C toggle, trust is implicit
System row changes:
  * Ariadne's Thread row has a direct open: the label jumps straight to
    the Ariadne plug-in sub-page (no intermediate landing). A toggle on
    the right runs ariadneToggle through the existing shared hook, so
    Ariadne can be turned on/off from the System page without opening it.
  * Names & Certificates row gets a master toggle. ON means at least one
    optional resolver is enabled; flipping it enables or disables every
    optional resolver together (BNS is always on either way). The per-
    resolver advanced fields are preserved, so toggling back ON restores
    the same configuration.
  * Aegis row is removed from System — Aegis stays as its own top-level
    nav entry, so having it in two places was clutter.
  * "About plug-ins on theseus.x" link moved from the System header to
    the plug-ins Ariadne sub-page, where it is actually about something.

Trust surface simplified:
  * Mozilla CA bundle and the Russian National CA are both always on.
    The Mozilla bundle was already always-on; the Russian CA defaults
    to enabled, scoped to .ru / .рф / gov.ru / online.ru. The scope
    keeps the Russian CA from signing for anything else on the web, so
    the UI toggle was moot — removed to shrink the Certificate trust
    section. The caRuOn and caRuScope inputs remain in the DOM as
    hidden placeholders so the existing init / save code keeps working.

Breadcrumbs on plugins-ariadne and plugins-aegis sub-pages now read
"System ›" instead of "Plug-ins ›" to match the renamed nav entry.
2026-10-27 23:01:11 +02:00
Local Dev
b1b393f02f Theseus 0.3.124 (cont'd): Ariadne nested under System; Theseus logo toggles the Settings tab
Ariadne's Thread drops out of the Settings top-level nav. It is reached
from the System section's chevron now; its page gets a System › crumb
back. Aegis stays top-level (user-facing wallet, used often enough to
earn its own slot).

The Theseus logo in the toolbar was open-only — the second click did
nothing. It now toggles: if Settings is already the active tab, the
click closes it (and switches to whatever tab Theseus falls back to).
Deep links that open a specific section (openSettings("ai-engines")
from a picker, say) still always open — toggling is the intent of the
logo click specifically, not of every open-settings call.
2026-10-27 21:57:32 +02:00
Local Dev
de1a5e18d4 Theseus 0.3.124: Open-with label trimmed; file assocs auto-on; Settings sidebar gets System (holds Names & Certificates)
Open-with menu label — Windows was showing the per-extension ProgID's
default value, which was set to "Theseus HTML Document". That looked
verbose next to the real brand name, and the per-ext label never changed
regardless of which extension the user right-clicked. Shortened to just
"Theseus Navigator". The ApplicationDescription under Capabilities is
dropped too — Default Apps uses it as a tooltip and the sentence it held
was noise.

File associations are now auto-registered on first launch. The toggle in
Settings is dropped: the entries live under HKCU with no admin, cause no
harm by being present, and the common case (right-click an .html on your
desktop, see Theseus in the Open-with menu) is strictly better than the
previous "toggle it on first" step. Two per-profile flags remember the
rollout (fileAssocsAutoApplied) and the one-time 0.3.124 label rewrite
(fileAssocsLabelFixed_1); a user who removes the entries by hand stays
opted out.

Settings sidebar — the Plug-ins nav entry is renamed System and now holds
a chevron to Names & Certificates (which is no longer a separate top-
level nav entry). The underlying section id stays "plugins" so the
plugins-ariadne / plugins-aegis crumbs and any existing deep links keep
working. Names & Certificates picks up a System › crumb at the top.
2026-10-27 21:50:06 +02:00
Local Dev
1d4e85f1d2 Theseus 0.3.123 (cont'd): Shield + Cookie Pop-ups now apply to sidebar AI panels
Shield (adblocker) already ran in the sidebar — it hooks the default
session's webRequest, so any WebContentsView on that session got the same
filter as a tab. Cookie Pop-ups (consent) didn't: the add-on-inject
preload asks main which scripts to run, and the gate required the sender
to be a web tab. Sidebar panels aren't in `tabs`, so sites loaded in the
sparkle-opened AI panel (and quick-link apps like WhatsApp, Telegram)
still showed every consent banner.

Fix is in injectionsForSender (and addon-page-msg for the inject's
round-trip back): also accept quickPanel.webContents and leftPanel's
sender as a "page" for the purpose of page-inject add-ons. The scripts
still see only the URL — nothing panel-specific — so no new attack
surface is opened; everything on the user's enabled page-inject list
runs on the same origins there as it does in a tab.
2026-10-27 21:05:05 +02:00
Local Dev
aea158ab05 Theseus 0.3.122 followups: AI engines page, Pick-AI edit button, Pithos panel, Did-you-mean on DNS failures, LLM picker UI polish, real-brand icon preference
Shipped on top of the 0.3.122 Settings restructure commit.

AI engines settings page. New top-level nav entry "AI engines" with its own
Default picker, Enabled list, catalog, discover filter and + Add AI engine
form. The Search page is now LLM-free — ENGINE_KINDS is `["search"]`, the
Search catalog filters out kind="llm" entries, and the Search custom-URL
form only adds kind="search" engines. add-engine IPC now accepts a kind:
"llm" field (sets defaultLlmId instead of searchEngine for LLM customs).

Pick-AI picker. Borders removed, corners rounded (16px), heavier shadow;
"Pick AI engines…" footer row dropped. Edit button (pencil icon) added to
the header; opens the new AI engines settings page via `llm-picker-settings`,
which now routes to the "ai-engines" slug (openSettingsTab falls through to
"search" for legacy profiles that lack the section).

Icon priority flipped. allEngines() now prefers a fetched favicon (the
site's own brand mark, cached per profile) over the bundled generic tile.
Bundled tiles still carry the first paint while the fetch runs, and the
emit after fetch swaps in the real brand. Offline profiles see the tile
indefinitely — same reliability as before.

Pithos sidebar panel. bundled-addons/pithos/addon.json declares a `panels`
block so sidebarLeftPanels() returns Pithos's panel BEFORE the add-on's
on-demand activation. Previously, the Sidebar settings' Theseus native
apps card was missing Pithos: it only appeared after first launch, when
the add-on's own registerSidebarPanel call ran. Hermes already did this.

Did-you-mean on DNS failures. The error page's "Did you mean" row now
merges BCNR warm-index matches with ICANN alternative-TLD swaps + history
base-name matches. For my.mynymbox.com the suggestions are my.mynymbox.io,
mynymbox.io, my.mynymbox.net, mynymbox.net — the subdomain-strip is
interleaved so a mistake like typing my.mynymbox.com when the real site
is client.mynymbox.io still surfaces mynymbox.io near the top. Both paths
are local-only; no network, no leak of what the user is browsing.

Sidebar settings tightened. "How panels open" collapsed to one row with
two side-by-side option cards; "Reset panel widths" and "AI engine in the
sidebar" are one-liners now.
2026-10-27 20:50:40 +02:00
Local Dev
41eb0acec9 Theseus 0.3.121: default-browser toggle + "Open with Theseus" in file menus
New Settings › General › Default handling section (Windows only, hidden on
other platforms until there is a backing path for them). Two toggles:

  * "Make Theseus the default browser" registers Theseus for http and https
    via app.setAsDefaultProtocolClient and lands the user on Windows
    Settings › Default apps so they can confirm the switch — Windows does
    not let an app assert itself as default, so we do what we can and point
    them at the UI that owns the final decision.
  * "Show Open with Theseus in file menus" writes HKCU\Software\Classes
    entries for .html, .htm, .pdf, .svg and .xhtml so Theseus appears in
    the Open-with dropdown for those files. Everything lands under HKCU
    (no admin). A matching RegisteredApplications\Theseus Navigator entry
    makes Theseus visible by name in Settings › Default apps.

Also handles file paths and URL arguments on the command line — this is
what Windows passes when the user picks Theseus from an Open-with menu, or
clicks a link in another app once Theseus is the default. argv[0] is the
exe; the first entry that is a recognised scheme (http/https/file/bns) or
an existing local file wins and opens as a new tab. Second-instance was
already wired to handleLaunch via requestSingleInstanceLock, so a running
Theseus just picks up the file.
2026-10-27 17:28:32 +02:00
Local Dev
fa2d2f89da Theseus 0.3.120: Pick-AI button opens its list again; "DuckDuckGo AI" renamed to "Duck AI"
The 0.3.106 switch from a native menu to an HTML overlay for Pick AI gave the
overlay a client-side window.blur handler that called api.close(). In the
engine picker (same pattern) the close-on-click-away is driven from main
with a `win.isFocused()` guard, so a focus flicker between the strip view
and the pop does not count as a click-away; the LLM overlay missed that
guard, so Electron's own view-to-view focus flicker on open was enough to
close the picker the moment it opened. From 0.3.106 through 0.3.119 the
Pick-AI button looked like a no-op: it rendered the pop internally (the DOM
was there, 7 rows) but setVisible flipped back off before paint. Users saw
a blank click.

Fix is the same contract the engine, language, downloads and site-info
pickers use: closeOnClickAway on main, no blur handler on the client.
`llmPickerVisible` is tracked alongside setVisible so the gate can read it.
The focus() call on open now runs only when the window is actually focused
(same guard the other overlays use). The raise() call also passed
`primaryW?.win` where a window record was expected, so the view never
re-parented when a secondary window became primary — fixed to pass the
record.

Also renames DuckDuckGo AI → Duck AI in the engine catalog. duck.ai is
Duck's own branded entry for the chat UI and matches what the host lands
on; the longer name was ambiguous next to the DuckDuckGo search entry.
2026-10-27 17:08:33 +02:00
Local Dev
47a739ad72 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).
2026-10-27 16:47:22 +02:00
Local Dev
61c605a97f Theseus 0.3.118: drop Phind (Vercel 404), re-bundle AI picker icons
Phind's web UI returns a Vercel 404 at the root as of 2026-10-27, so
users who clicked Open AI with Phind as the default got a dark error
page. The engine is now marked frozen with a reason, which keeps the
Settings row visible with an explanation but takes it out of the
enabled list; anyone whose defaultLlmId was phind automatically falls
back to the next enabled engine (Perplexity).

AI picker icons move from runtime favicon fetch back to bundled files
(ChatGPT, Grok, Gemini return as engine-icons/*.svg — initial-on-color
tiles). The fetch path still runs as a fallback for custom engines and
anything else that lacks a bundle.
2026-10-27 16:01:36 +02:00
Local Dev
34989f94b3 Theseus 0.3.117: ICANN hosts that fail DNS show a DNS error, not a BCNR-register pitch
When a navigation hits ERR_NAME_NOT_RESOLVED and the TLD is a well-known
ICANN one (.com/.net/.io/country codes/…), Theseus now shows the DNS-
flavoured 'This name didn't resolve' page instead of the BCNR-flavoured
'That name isn't registered' page. The BCNR page framed the failure as
'nobody has claimed this on-chain name, want to register it on Sirius?'
— confusing when the user typed a real .com whose DNS is temporarily
broken (hostile Wi-Fi AAAA mangling is the usual cause). The DNS page
leads with retry and search instead, and still mentions BCNR was tried.

Non-ICANN TLDs (.bch, .x, …) keep the register-first framing. The
TLD set is a static whitelist of the common ones — covers the long
tail of real sites without being exhaustive. Add more as needed.
2026-10-27 15:35:03 +02:00
Local Dev
f87173fde4 Theseus 0.3.115: AI picker chevron now visible; strip + picker refresh after favicon fetch
The sidebar AI button's chevron badge grows from a 10 px grey ghost in
the corner to a 14 px acid-coloured circle that reads at a glance, so
Pick AI engine is actually discoverable. Click or Enter still opens
the picker overlay; right-click on the AI button still works too.

Also wires emitQuickLinksState() into the icon-fetch completion path.
Before 0.3.115 the sidebar strip and the picker overlay kept showing
the engine sym emoji until some other state change re-emitted the
quicklinks payload. Now a freshly-fetched favicon lights up in the
strip and the picker on the same tick it finishes caching.
2026-10-26 10:50:47 +02:00
Local Dev
8bb5b3d26a Theseus 0.3.114: add-on update poller fires after chrome, not during tab restore
Moved the 30-second boot poll from whenReady+30s into onChromeReady so
restoreTabs' network fetches aren't competing with the add-on manifest
fetches for the first few seconds. The 4 h interval stays where it was.

Preload audit (no change needed): theseus-id-preload.js already short-
circuits in subframes (window.top === window guard), addon-inject-
preload.js keeps page scripts top-frame only by design, and
no-badge-preload.js intentionally covers service workers.
2026-10-25 12:51:27 +02:00
Local Dev
bd55e75536 Theseus 0.3.113: AI picker shows the real brand favicons
The ChatGPT, Grok, Gemini and Phind rows in the sidebar AI picker now
pull each site's own favicon through the same fetch-and-cache path
custom engines already use. The old placeholder color-letter tiles I
shipped in 0.3.106 are removed; the engine's sym emoji is the pre-fetch
fallback until the real favicon lands (cached per profile after that).

Change: fall back from bundledIcon(id) to customFavicon(https://<fav>/)
for built-in engines when no bundled file exists. Perplexity keeps its
existing bundled perplexity.png.
2026-10-25 10:47:40 +02:00
Local Dev
9095a5ecf9 Theseus 0.3.112: AI picker chevron fixed, home polish, performance toggles
Three home-page tweaks:
- Removed the YOUR LINKS and SILENT MODE section headings; the two
  panels now stand on their own without labels.
- The + Add card cell now matches the real cards' size and shape so
  it reads as a peer of the grid rather than a short dashed strip.
- Empty slot cells in the left grid are invisible by default and
  only reveal their dashed outline when you hover the strip or drag
  a link over them. The + add-link cell stays visible as the
  discoverable entry.

AI engine picker:
- The chevron badge on the AI button is now a plain span with the
  button role, not a nested <button> inside the main AI button.
  Chromium flattened the invalid nesting so the chevron's own click
  handler never fired; the picker now opens from the chevron and
  from keyboard Enter / Space as well as right-click.

Performance (Settings > Performance > Startup):
- Pithos ships with activation: on-demand; its control server for
  s3d no longer boots at launch. Wakes on first panel open or a
  pithos.sia navigation.
- Hermes relay auto-restore (1.5 s after launch) is now gated by a
  new setting hermesAutoRestore (default on). Turn it off to skip
  background Nostr relay connections for users who don't live in
  Hermes.
- New setting pithosAtLaunch (default off) mirrors the existing
  walletAtLaunch so users who do want Pithos ready at launch can
  opt back in.
- The Lightest preset now also turns off pithosAtLaunch and
  hermesAutoRestore.
2026-10-24 14:20:20 +03:00
Local Dev
3ab3f77594 Theseus 0.3.109: Save page as PDF or PNG; connector design doc hosted on theseus.x
Right-click on a tab now shows a Save page as submenu with PDF and
Image (PNG) items. PDF uses webContents.printToPDF (A4, prefers CSS
page size, prints backgrounds); PNG uses webContents.capturePage of
the visible viewport. Both open a save dialog with a filename derived
from the tab title or hostname, write to the chosen path, and register
the result in the downloads list.

The Claude connector's design doc now ships at
theseus.x/dev/claude-connector/DESIGN-claude-connector.md so readers
on the site do not have to leave for the forge; the Developers page
links the local copy first and the forge mirror alongside it.
2026-10-23 23:00:42 +03:00
Dev
c06557e957 Theseus: Claude connector, an opt-in MCP server for the signed-in profile
Claude sessions could not work inside the user's own profile: the desktop
app's browser lost synthetic pastes and typing in Medium's editor, and a
browser-wide --remote-debugging-port would hand every session to any local
process. The connector is a built-in extension, off until turned on in
Settings > Extensions, that serves MCP on 127.0.0.1 behind a per-install
token and drives one tab at a time through that tab's webContents.debugger.

- Host: a "tab-control" capability (built-in add-ons only) for listing,
  opening, navigating, closing and focusing tabs, handing out web tabs'
  webContents (never Settings, extension or home tabs), and a toolbar chip
  plus tab outline while a client is connected; the chip's X stops it.
  Built-in add-ons can ship "defaultEnabled": false.
- Tools: list_tabs, open_tab, navigate, activate_tab, close_tab, screenshot,
  read_page_text, snapshot (accessibility tree with refs), click, type
  (insertText + real Enter), press_key, paste_html / paste_text (system
  clipboard + webContents.paste, clipboard restored), upload_file
  (DOM.setFileInputFiles), wait_for, and evaluate behind its own switch.
- Safety: first use of each site asks the user; password and one-time-code
  fields are refused; uploads only from folders the user added; requests
  from web pages or foreign Host headers are refused; every action is
  logged with a timestamp in the panel and actions.log.
- Claude Desktop runs stdio-shim.cjs through the Theseus executable in Node
  mode.
- Tests: unit (protocol, auth, policy, shim) and an end-to-end run on a
  throwaway profile that types, pastes HTML with a heading and a link, and
  uploads a PNG on a local page.
2026-10-23 17:45:02 +03:00
Local Dev
fde510eece Theseus 0.3.106: AI engine picker as a styled overlay with real icons
Right-click or chevron-click on the sidebar strip's AI button now opens
a borderless overlay instead of a plain native menu: enabled engines
are listed with their bundled icons, the current engine is highlighted
with the acid accent + check, and a settings row at the bottom jumps
to Search settings. Clicking an engine selects it as the default and
opens it in the left panel in one click.

Bundled engine icons gained an svg-first fallback: engine-icons/<id>.svg
is picked up before <id>.png so plain color-coded letter tiles ship
alongside the existing bitmap favicons. Added tiles for ChatGPT, Grok,
Gemini and Phind — each a simple initial-on-color mark.
2026-10-22 22:06:37 +03:00
Local Dev
727fa27ebd WizardConnect "Open in wallet" links that open a new window reach Aegis
Potidaea's "Open in wallet" is <a href="wiz://…" target="_blank"
rel="noopener noreferrer">, a shape many dapps use. A new-window wiz:// link
goes through the window-open handler, which credits a pairing to the page
only through the request's referrer, so it can tell the page's own link
from one in a frame. noreferrer strips the referrer, so the link was
dropped and the wallet never heard of it.

The inject preload, which runs in a tab's top document only, now hands a
trusted click on a wiz:// link straight to main, and main accepts it only
from the tab's main frame before routing it like any pairing link. Links
inside iframes still go the old way and are still refused without a
referrer.
2026-10-22 19:15:05 +03:00
Local Dev
3b2cad491d hermes: ship the browser side of the Theseus feature set
Fixes the "unknown invoke: fetchCloudBackup" dead-end on mobile sign-in
and the empty hooks the Settings UI depended on. The shim now implements:

- Local wrap: on signup it generates a BIP-39 mnemonic (@scure/bip39),
  derives the Nostr sk via PBKDF2+HKDF with purpose "messenger/0" (same
  chain Theseus runs), scrypt+AES-GCM wraps the mnemonic (@noble/hashes
  scrypt matching HERMES_SCRYPT N=2^15 r=8 p=1), stores it in
  localStorage.hermes.wrap. hasBackup/getBackup use that wrap, so a
  password sign-in now works on the same device.

- Cloud backup: publishCloudBackup / fetchCloudBackup / removeCloudBackup
  / hasCloudBackup matching Theseus's dtag format
  (hermes.backup.v1/<sha256(bareName)[:32]>). Password unlocks the local
  wrap, re-wraps for the cloud copy with a fresh salt, publishes a
  kind:30078 to every relay, remembers the event id for later retract
  via NIP-09.

- Phone discovery: setPhone / clearPhone / findByPhones with the same
  hermes.phone/<base64url(sha256(E.164))[:32]> d-tag Theseus uses, so a
  vCard import on the browser surfaces the same matches a Theseus user
  would see.

- contactsUpdate / contactsRemove rounded out so the panel's contacts
  menu is fully wired.

Also:

- Default relay list bumped to [wss://hermes.x, wss://relay.silentmode.st,
  wss://nos.lol] in both the Theseus host and the web shim, so every
  publish/fetch hits our own strfry on the VPS and the cloud backup lives
  somewhere we control.

- Theseus host: addons-host.js + main.js now understand a `width` field
  on sidebar panels, so the Hermes panel declares width:500 and opens at
  a Telegram-ish width by default (user can still drag; saved per-panel).

- Panel + web messenger: forced color-scheme:dark (the brand mark has
  hard navy cutouts that stand out as "black inside the envelope" on a
  light background; dark everywhere is cheaper than theme-aware marks).

- Password fields: 👁 toggle appears on every <input type="password">
  via a tiny JS enhancer in both the panel and the web messenger.

- Settings/signin tabs: Sign in / Sign up persistent pill, drag-to-resize
  contacts/thread splitter (persisted per device), 2-column always.
2026-10-22 15:33:07 +03:00
Local Dev
b2fef43607 Theseus 0.3.103: sidebar panel context menu + Hermes icon framing
Right-click on a sidebar panel (WhatsApp, Telegram, LLMs, add-on panels
like Hermes) now opens a native menu with Copy image / Save image as /
Open link in new tab / Copy / Back / Forward / Reload. Previously the
sidebar views had no context-menu listener attached, so sites like
WhatsApp Web that intercept right-click left the user with no way to
copy an image.

Hermes mark in the sidebar strip now zooms to the V-fold and wings;
envelope body partially visible. The original viewBox had ~43% empty
space top-and-bottom, so the glyph rendered at ~15 px inside the 26 px
icon frame.
2026-10-22 13:48:09 +03:00
Local Dev
bbe5d3d298 hermes: cloud-wrapped backup (opt-in B) + mobile site polish
Users can now sign in with name + password on a device that has never seen the
account by opting into a cloud backup at account creation. The seed phrase is
locally re-wrapped with scrypt + AES-GCM keyed by the password and published
as a NIP-78 kind:30078 event under d-tag `hermes.backup.v1/<sha256(name)>`.
Relays only ever see opaque ciphertext; the password is the only decryption
key, so backup strength is password strength.

Signin tries the local wrap first (fast, no network) and falls back to the
cloud copy if the device hasn't been used before. Settings → Backup now has
"Back up to cloud" / "Re-upload" / "Remove cloud backup" controls that reuse
the Reveal-seed password field as the key.

Site: added @media breakpoints to shared.css so the header collapses cleanly
on narrow screens (icon-only brand under 380px, hidden "Sign in" label under
640px), the hero mark drops to 84px, h1 scales down, and buttons shrink to
touch sizes. Also fixed a stale reference to the removed `mnemonicBox` id in
the Create-account toggle that was throwing a TypeError on mobile.
2026-10-22 03:46:45 +03:00
Local Dev
4c10e3e724 hermes: lift scrypt maxmem so Create account doesn't throw
N=2^15 r=8 p=1 needs 128 * N * r = ~32 MiB. Node's default maxmem for
scryptSync is exactly 32 MiB, so the derive call throws
MEMORY_LIMIT_EXCEEDED on the first create-account click. Pass maxmem:
128 MiB explicitly so the ceiling is above the KDF's working set with
headroom.

Applies to both wrap and unwrap paths; wrap params carry the KDF cost
inline so changing the N here would invalidate existing backups, but
unwrap already reads N from the blob — the maxmem lift is the only
needed change.
2026-10-22 00:10:19 +03:00
Local Dev
13d4ab76b3 Theseus 0.3.101: Grok + Gemini + ChatGPT, sidebar polish
Three more LLM engines land in the catalog and in DEFAULT_ENABLED, so the
sparkle button's picker lists five AI engines out of the box: Perplexity,
Phind, ChatGPT, Grok, Gemini. The first two answer a URL query without any
login, the latter three need a free-tier account; all three accept the
chat URL as the "open the home" target, which is what the sidebar button
needs. A one-time offer migration adds them to any existing profile's
enabledEngines (users who disable one keep it off across restarts via a
new `enginesOffered` field).

Sidebar strip polish. The gear button now opens Settings › Sidebar on a
single click instead of popping a one-item native menu first. The "+"
add button under the gear is removed — adding a web app goes through
Settings › Sidebar anyway, which the gear opens. The quicklinks-add IPC
is kept but repointed to Settings › Sidebar (it used to open General,
which was the wrong page for the add-a-web-app flow).
2026-10-21 21:55:10 +03:00
Local Dev
22e2b3f75e Theseus 0.3.100: LLM sidebar button, Hermes consolidation, Settings polish
The gear popover at the bottom of the left strip is reduced to a single
"Open sidebar settings" item; the overlay/push radio and "Reset panel
widths" controls move to Settings › Sidebar permanently, so there's one
source of truth for the sidebar's own options.

A new sparkle button is added below the icon stack: it opens the user's
default AI engine (any search engine with kind=llm — Perplexity ships
on by default now; Phind is in the catalog). Click opens the engine in
the left panel like the existing web-app quick-links; right-click (or
the small chevron in the button's corner) pops a native menu of every
enabled LLM, each one-click to switch default + open. The button hides
itself when no LLM engine is enabled.

Hermes consolidation. The hermes.x web quick-link added in 0.3.99 is
retracted — the bundled Hermes extension already registers a left-strip
panel (side: "left"), so the web link was duplicating it. Any profile
that caught 0.3.99 gets the stray entry yanked on first load.
Ctrl+Shift+E now opens the Hermes panel in the active window's left
sidebar instead of the standalone Messages BrowserWindow; the window
is still reachable via the ⧉ pop-out button in the panel header for
users who want a free-floating client. The home-page Silent Mode card
for Hermes.X comes back (it's a link to the web page, not a shortcut
to the panel — different purpose).
2026-10-21 20:10:11 +03:00
Local Dev
208a192fc9 Theseus 0.3.99: SNS + Unstoppable adapters, Hermes moves to the sidebar
Two more resolvers under Settings › Names & Certificates. SNS — .sol names
resolve through Bonfida's public SDK proxy, preferring an explicit URL
record over an IPFS record (served via a configurable IPFS gateway).
Unstoppable Domains — the full UD TLD roster (.crypto, .nft, .wallet,
.bitcoin, .blockchain, .dao, …) through resolve.unstoppabledomains.com;
browser.redirect_url takes precedence over an ipfs record. .x stays with
BNS — the UD adapter explicitly skips it so a Sirius registration can
never be shadowed by an Unstoppable one.

Both proxies are Cloudflare-fronted; users on blocked IPs can swap the
endpoint in Advanced. The handshake adapter's skip-list grows to cover
.sol and every UD TLD so a user with HNS + UD + SNS all enabled gets the
specific adapter, never the generic hns.to gateway, for those names.

Hermes.X moves from the home page's Silent Mode card grid to the Theseus
left-sidebar quick-link strip, slotting in right after Proton Mail. The
default list grows to 6 entries; existing profiles pick it up through the
LATER_DEFAULTS one-time offer (same mechanism Proton used in 0.3.88).
Users who still have Hermes on their custom home page can remove it manually.
2026-10-21 19:12:19 +03:00
Local Dev
5e27a1b53d hermes: phone discovery (opt-in), lookup contacts by number
Users can link one or more phone numbers to their Hermes identity by
publishing a kind:30078 claim event whose d-tag is a SHA-256 hash of the
E.164 number. The number itself never leaves the device. Add-contact and
message-send now also accept a +phone input directly — the client hashes it
and queries relays for the matching Hermes identity.

- lib/hermes.js: normalisePhone(str) strips separators + a leading 00
  into E.164, rejects anything that doesn't fit +[country][7-15 digits].
  hashPhone(str) → base64url-truncated-to-32 SHA-256 digest, used as the
  d-tag suffix under PHONE_DTAG_PREFIX. buildPhoneClaimEvent /
  buildPhoneRetractEvent emit the signed kind:30078 / NIP-09 kind:5.
- main.js: _hermesAPI.getPhone / setPhone / clearPhone / findByPhones.
  Plaintext phone persists in the identity meta (locally only) so the
  user can see what's linked and retract it; event ids are kept so a
  retract can reference the exact wire event. hermesResolveTo takes a
  phone-shaped input and does the discovery lookup transparently, so
  contactsAdd and send accept phones without a new entry point.
- panel.html: Settings → Phone discovery (link / unlink + privacy note),
  add-contact placeholder now lists +phone alongside the other forms.

Privacy stance stated in the UI: "anyone who already knows your number
can find you — same tradeoff as number-based messengers." No PSI tricks
yet; plain hash. Users who don't want it just don't link, which is the
default. Future slice can add a pepper if operators want to narrow the
brute-force window.
2026-10-21 17:21:16 +03:00
Local Dev
b5b3e5c1b2 hermes: Nostr kind:0 profiles — display name, picture, about
Peers' chat-list labels now cascade: contact nickname → kind:0 display name →
BNS handle → pk preview. Avatars render as a URL picture when kind:0 carries
one, with initials as fallback. Profiles are fetched on demand (background,
non-blocking) when a new peer pk shows up in the inbox or contact list, and
cached on disk so a cold start renders instantly.

- lib/hermes.js: buildProfileEvent({sk, displayName, picture, about}) emits
  a signed kind:0 with `name` + `display_name` set together (clients vary
  on which they prefer). parseProfileContent(content) handles both.
- main.js: profile cache at <userData>/hermes/profiles.json; auto-fetch
  from HERMES_DEFAULT_RELAYS with a 4 s per-relay cap. hermesPublishEvent
  centralises relay publish (used by profile save; send() retains its
  inlined copy for the DRY-up later). hermesRecord() kicks off a background
  profile fetch the first time a peer is seen; result fires on the
  hermes-profile bus event.
- main.js: _hermesAPI.updateProfile / getProfile. Addon proxies both.
- panel.html: Settings → Profile editor (display name, picture URL, about);
  publishes on save, pre-fills from the cache. Picture validated as http(s).
  labelFor() + avatarFor() centralise the display cascade. Profile state
  lives in state.profiles.
2026-10-21 17:18:07 +03:00
Local Dev
cee34c47e5 hermes: name+password signup, Settings panel, seed backup gated by password
Third signin option on the panel: enter a bare name + password, Hermes mints
a 12-word BIP-39 mnemonic locally, derives the Nostr key, password-wraps the
mnemonic for later Settings → Backup, and persists the sealed sk the same
way the other paths do. Save-forever still handles routine signin — the
password is only used to reveal the seed phrase and only from Settings.

- main.js: hermesWrapMnemonic / hermesUnwrapMnemonic via scrypt (N=2^15) +
  aes-256-gcm. Wrapped blob at <userData>/hermes-identity/mnemonic.wrapped.json,
  plaintext JSON — the wrap itself is the protection. On sign-out the blob
  is nuked alongside the sealed sk.
- main.js: init() now takes { create: true, handle, password }. Handle is
  validated (1-32 chars, kebab-friendly) and stored as `<name>.erm` so a
  mainnet free-manifest reservation lands on the same canonical form later.
  Mnemonic-path init optionally takes a password too — "promote this
  seed-phrase session to a password-protected backup" in one step.
- main.js: new _hermesAPI.getBackup({password}) and .hasBackup. status() now
  returns handle + source so the panel can label the restored session.
- panel.html: "Create a new account" button on signin reveals handle +
  password + confirm. ⋯ menu adds Settings… showing account info, display
  mode picker (hermes:alice / alice.erm / alice@hermes.tel — persisted via
  silentmode.storage), and the gated seed-phrase reveal. Reveal lays words
  out 12-across with 1-indexed numbering so a user copying to paper doesn't
  miscount. Backup section hides for vault / mnemonic sessions.

Still off-chain only — handles created this way are local labels until the
mainnet mint of the free manifest lets us register them against the
`hermes.erm` signed-records store (see [[hermes-name-scheme-plan]]).
2026-10-21 17:14:26 +03:00
Local Dev
4133153f32 hermes: three-form handle parser, hermes: scheme display, save-forever signin
Panel + standalone window now accept all three handle forms as synonyms, and
the UI defaults to the hermes:alice scheme form. Signin is persistent across
restarts via safeStorage-sealed identity; the ⋯ menu adds Sign out.

- lib/hermes.js: parseHandle(input) → {kind, value} canonicalises any of
  hermes:alice, alice.erm, alice.bch, alice@parent.tld, npub1…, or raw hex.
  renderHandle(name, mode) formats a .erm name as hermes:alice (default),
  alice.erm (dotted), or alice@hermes.tel (email). Non-.erm names always
  render dotted so a .bch handle can't masquerade as a sub-identity.
- main.js: hermesResolveTo() unifies contacts-add + send + their panel-API
  twins behind one path. Sub-identity (alice@parent.tld) resolution returns
  a crisp "not available yet" until the mainnet mint of the parent name's
  signed-records manifest lands — the parser accepts the form today so UI
  copy and placeholders can show it.
- main.js: safeStorage-sealed identity at <userData>/hermes-identity/,
  auto-restored on app ready. New _hermesAPI.signOut wipes it. init() takes
  { remember: false } for a one-shot session (default: persist). A
  hermes-restored event fires on auto-restore so the panel skips the
  signin screen.
- panel.html: renderHandle() mirror client-side; ⋯ menu with "Signed in as
  hermes:alice" header + Sign out; placeholders show all three forms; the
  signin hint tells users they stay signed in.

On-chain `.erm` and `hermes.tel` mints are deliberately deferred to mainnet
per user direction — the parser and display paths are tld-agnostic, so a
mainnet switch is one constant change in lib/hermes.js (HERMES_TLD /
HERMES_EMAIL_PARENT) plus the panel's mirror of them.
2026-10-21 12:32:59 +03:00
Local Dev
8777b1fc56 hermes: in-panel messenger with Theseus ID signin, spread-wings mark
The sidebar panel used to be a launcher that opened the standalone Messages
window; now it IS the messenger — signin screen with "Open with Theseus ID"
(derives the Nostr key from the unlocked vault seed) or "Open an existing
account" (12/24-word mnemonic fallback), then a contacts + thread view with
a narrow-width single-column fallback. The ⧉ button still pops the standalone
window out, so the Ctrl+Shift+E flow keeps working.

- main.js: expose a global._hermesAPI with status/canUseVault/init/inbox/
  send/markThreadRead/contacts* so the addon can proxy panel calls without
  granting it ipcRenderer or crossing the HERMES_ONLY sender gate.
  hermesEmit also fans out on an in-process __hermes_bus so the panel gets
  live inbox/status pushes decoupled from hermesWin's lifetime.
- bundled-addons/hermes/index.js: proxies each allow-listed method onto
  global._hermesAPI, forwards bus events to api.emit for the panel.
- panel.html: signin + app screens, mobile-style single column under 540px.
- Mark updated to the spread-wings variant: envelope sized up (34×22),
  three tapered trails extending outside the viewBox so the wings don't
  bunch at the back of the envelope at any size. Applied to the addon
  icon (manifest base64), the panel header, both /hermes sites, and
  site-hermes-x's favicon + mark SVGs.
2026-10-21 03:00:17 +03:00
Local Dev
227d013013 Theseus 0.3.98: Namecoin + Handshake adapters
Two more adapters under Settings › Names & Certificates:

Namecoin — .bit names resolve by calling name_show "d/<name>" on the
configured JSON-RPC endpoint and following `translate` or `alias` records
to a clearnet host. Pure IP records aren't followed yet (that needs
in-browser DNS override + TLS pinning, which comes later). Namecoin has
no free public RPC, so the toggle is off by default and the row carries a
"Needs an RPC URL" note instead of a "Not wired yet" one; set yours in
Advanced.

Handshake — non-ICANN hostnames resolve through the public hns.to web
gateway (user-overridable in Advanced). hns.to proxies the request to a
Handshake node and serves the on-chain content. A bundled list of common
ICANN TLDs (original gTLDs + popular new gTLDs + every ccTLD) keeps the
default collision policy ("icann-wins") from hijacking clearnet names.
Setting the policy to "hns-wins" removes that gate.

Both adapters follow the ENS adapter's shape — tryExtraResolvers in main.js
calls each in turn after the BNS lookup; the first one that returns a URL
loads it. Settings copy on both rows updated.
2026-10-21 02:40:33 +03:00
Local Dev
3985772ba3 Theseus 0.3.97: ENS adapter — .eth names resolve to IPFS/IPNS
First real resolver behind the Names & Certificates toggles. When the ENS
switch is on, typing a .eth name in the address bar runs:
  1. namehash(name)                  (EIP-137 keccak256 recursion)
  2. eth_call  resolver(bytes32)     on the ENS registry
  3. eth_call  contenthash(bytes32)  on the returned resolver address
  4. decode EIP-1577 (varint protocol + CID) → ipfs|ipns|swarm
  5. navigate to <gateway>/ipfs/<cid> (or /ipns/<cid>)

The adapter lives in lib/resolvers/ens.cjs; main.js's navigateTab calls it
through tryExtraResolvers after the BNS check and before the clearnet
fallback. Defaults: publicnode's free Ethereum RPC (Cloudflare's eth-RPC
returns "Internal error" for ENS calls in testing) and ipfs.io as the
gateway (Cloudflare retired their IPFS gateway in 2024). Both are
user-overridable in Settings › Names & Certificates › Advanced.

CIDv0 (Qm… base58) and CIDv1 (bafy… base32) both encode; swarm names
cache a "not yet supported" negative result for one minute until we add a
swarm gateway option. Positive answers cache for 10 min, negatives for 1 min.
2026-10-21 02:20:23 +03:00
Local Dev
5d34fa18af Theseus 0.3.95: Names & Certificates settings — UI shell for extra resolvers
New top-level settings page lets the user pre-configure which non-BNS name
systems Theseus will resolve (ENS, Namecoin, Handshake, SNS, Unstoppable)
and which extra TLS roots it will trust (Russian National CA, scoped by TLD).
BNS is always on; everything else is off by default. Each resolver row has
its own Advanced disclosure for RPC URL, gateway, endpoint and collision
policy. The Russian CA row's Advanced holds the comma-separated TLD scope
list that limits what the CA can sign for (default .ru/.рф/.gov.ru/.online.ru).

State persists to %APPDATA%\Theseus\extra-resolvers.json via settings-only
IPC (extra-resolvers-get / extra-resolvers-set / extra-resolvers-reset,
origin-gated to the settings page). The adapters and setCertificateVerifyProc
hook that read this file land in 0.3.96 (ENS) → 0.3.99 (Russian CA); each
row's "Not wired yet — coming in 0.3.9X" caption goes away as its adapter
ships. No home.html change in this release.
2026-10-21 01:19:06 +03:00
Local Dev
8eae448dde Hermes: Ermis shortcut (Ctrl+Shift+E), sidebar add-on, vCard import, brand kit
Shortcut: Ctrl+Shift+M -> Ctrl+Shift+E. Chrome owns Ctrl+Shift+M as
'switch profile' and E matches the Greek spelling (Ermis).

Sidebar discoverability: new bundled add-on at bundled-addons/hermes/
registers a left-strip icon + launcher panel. The panel is a thin chrome
(mark + 'Open Messages' + shortcut hint) that forwards clicks through
api.onMessage -> ipcMain.emit('hermes-open-request') -> openHermesWindow.
All real messaging code stays in main.js — add-on is purely for discovery.

Address book: opt-in vCard (.vcf) import. Dialog in the Add Contact modal
lets the user pick a file; main.js parses BEGIN:VCARD blocks for X-BNS-NAME
/ X-NOSTR-NPUB / X-NOSTR-PUBKEY plus .bch names and npubs mentioned in
NOTE fields. Candidates are previewed per-contact with checkboxes; nothing
is added until the user confirms. Non-matching vCards are returned too (so
the user can still add manually) rather than silently dropped. Nothing is
uploaded; parsing is local.

site/hermes: status badge flipped from 'designed - not yet built' to
'MVP - desktop'. New 'What ships today' grid covers threaded chat, send by
name, address book, local history (all live) and mobile + Tor (next /
planned). Hero carries the new Ctrl+Shift+E shortcut and a link to
/hermes/branding.

site/hermes/branding: new page. Mark SVG (winged envelope, two variants
for 16-20px and 24-160px display sizes), palette (reuses Silent Mode
tokens + an amber accent that's distinctly warm-yellow, not Hermes-orange
— so it never collides with Hermès the fashion house), name explanation
(English Hermes / Greek Ermis), voice notes, do/don't table, MPL-2.0
attribution.

Hermes/MOBILE-RECOMMENDATION.md: analysis of three mobile paths (inside
Ariadne / standalone / hybrid). Recommendation is Option 1: ship as a
screen inside Ariadne. Reuses the wallet seed, aligns with the design
doc's 'one seed many purposes' architecture, lowest total cost.
2026-10-21 00:45:25 +03:00
Local Dev
a3b20a2446 Hermes MVP: threaded chat UI, contacts, persistent history, --messages flag
Builds on the previous Hermes sessions (NIP-17 crypto + chipnet hermes.bch
+ Theseus Messages window) to turn the flat inbox into something usable.

main.js (hermes block):
  - Persistent inbox per identity at
    <userData>/hermes/<pkHex>/inbox.jsonl (append-only JSONL, replayed on
    init). Read-state at <userData>/hermes/<pkHex>/read.json so unread
    badges survive restarts.
  - Address book at <userData>/hermes/contacts.json: list / add / update /
    remove. hermes-contacts-add resolves .bch name OR npub OR hex pk,
    canonicalises, writes.
  - Reverse-resolve consults contacts first, chain second: a user-curated
    nickname wins over the on-chain np lookup.
  - hermes-send also records the outgoing message to the inbox so thread
    view shows both sides (only when at least one relay accepted).
  - Inbox messages carry direction + peerPkHex + peerName so the renderer
    can group by thread without re-doing the pairing logic.
  - --messages CLI flag opens the panel at launch (first instance via
    whenReady, second-instance via handleLaunch) so the dev harness and
    power users don't need Ctrl+Shift+M.
  - Dev-only auto-init: THESEUS_HERMES_DEV_MNEMONIC env, gated on
    THESEUS_USER_DATA so it refuses to touch a production profile.
  - HERMES_INBOX_LIMIT raised 200 -> 2000 now that history actually sticks.

messages-preload.js:
  - Adds hermes.contacts.{list, add, update, remove} and
    hermes.markThreadRead; status + onMessage/onStatus unchanged.

messages.html:
  - Replaces the flat inbox with a two-column layout: contact list (search
    + unread badges + last-message preview) on the left, selected thread
    on the right with sender bubbles, timestamps, inline Enter-to-send
    compose, remove-contact affordance.
  - .bch suffix stripped from displayed names (TLD is noise in chat UI;
    other TLDs stay as disambiguation).
  - Mark-thread-read fires on open; vault-bind path kept intact.
2026-10-20 23:21:34 +03:00
Silent Mode
8ac8b549b9 Theseus 0.3.91: home — hero back, Silent Mode cards, free-drag Your-links
Three changes to the desktop home that landed in 0.3.90:

- Hero header is back. The compass mark, Theseus Navigator title, tagline
  and search sit centered at the top of the page, same shape as the home
  before the desktop redesign. The Edit button moves to the top-right
  corner so the hero reads as identity, not chrome.

- Silent Mode on the right is CARDS again, not just tiles. Each card
  carries the brand icon on the left, title + one-line description
  stacked, and a muted acid-colored badge on the right (Navigator /
  Registrar / Code host / ...). Cards sit in a center-right column that
  stops before the right edge, giving the left column breathing room.

- Your-links on the left is free-drag, OS-desktop style. Each icon
  stores x,y and snaps to a 20px grid; dragging an icon moves it live
  while the grid faintly shows underneath. The schema gains x,y on
  Your-links items — unchanged for Silent Mode cards. Legacy icons
  without x,y auto-layout in a tidy 2-column grid near the top.

Compass mark replaces the chain emoji in the hero. The on-disk schema
nudges to v4; v3 and v1 reads still migrate (missing x,y get an
auto-layout fallback at render time).
2026-10-12 09:38:09 +02:00
Silent Mode
94ec382f20 Theseus 0.3.90: a desktop home page — two columns, brand icons, pick-and-move
The new-tab page is now a two-column desktop. The right column holds the
curated Silent Mode X-family (Theseus.X, SilentMode.X, Sirius.X,
Hephaestus.X, Prometheus.X, Hermes.X, Helios.X, Ariadne.X, Aegis.X) with
real brand marks pulled from each product's own favicon or add-on manifest.
The left column is yours — hello.bch, sia.coin, Pithos.sia, Bergamot.X by
default, plus whatever you add. Icons pick up and move within and across
columns in edit mode.

Edit mode also carries per-column default-size pickers (S / M / L / XL),
six background presets + a custom colour + an image upload, and + slots
in each column. The Ariadne.X mark uses the real face/thread illustration
in ancient-Greek-pottery colours (terracotta rings on cream). The Aegis.X
tile matches the one the add-on itself ships.

The on-disk format moves from a bare array of cards (v1) to a v3 object:
  { version:3, iconSize, quickSize, background, sections:{ sm, q } }
On first read, a v1 array lands as sections.q and the Silent Mode column
stays at the code default. The remote home-cards.json URL is still
accepted as either shape; migrateCards() normalises before use.
2026-10-12 01:41:17 +02:00
Local Dev
f6d71bd48f Theseus: switch sidebar apps and extension panels on and off
Settings › Sidebar had a Hide button for extension panels and only Remove
for web apps. Every row now has an on/off switch: off takes the app off
the strip and closes its panel, but keeps it in the list with its sign-in
and width. Web apps and panels share the store (leftPanelsHidden), and a
link that would open in a switched-off app's panel opens in a tab.
2026-10-08 01:43:03 +02:00
Local Dev
59d1c5ad56 Theseus: drag sidebar icons into any order
The strip always drew extension panels first and web apps after them,
in a fixed order. Web apps and panels now share one order (stripOrder)
that the icons can be dragged into; reordering web apps in Settings
moves them on the strip too, and a new app or extension goes to the end.
Until the strip is rearranged, Proton Mail leads, above the panels.
2026-10-08 01:30:33 +02:00
Local Dev
a0e4641ba2 Theseus: sidebar links you add get their icon; Proton Mail on top
A link added by hand gets an id like "youtube-k3f9", and the strip only
looked icons up by id, so YouTube or Discord added in Settings showed a
letter. The bundled marks are now also found by the site's address, and
any other site shows its own favicon (the letter when it has none).
Proton Mail leads the web apps, for new strips and where it is added to
an existing one.
2026-10-08 01:28:31 +02:00
Local Dev
d4d297b69e Theseus: an add-on's link to a sidebar app's site opens in that app
An add-on's "Send on Telegram" used to open web.telegram.org in a new
tab. Theseus already has Telegram and WhatsApp in the sidebar, signed
in, so a link to the site of an app on the strip now opens in its panel
at that address (a share screen, a chat). Everything else still opens
in a tab.
2026-10-08 01:08:38 +02:00
Local Dev
dbf2b95c80 Theseus: Proton Mail in the sidebar
Proton Mail joins the default web apps on the left strip, with its own
icon. A saved strip never picked up new defaults, so a web app added to
the defaults later is put on existing strips once; one the user removes
stays removed (quickLinksOffered).
2026-10-08 01:04:56 +02:00
Local Dev
3861925811 Theseus: a tab can go back into another window
A tab moved to its own window had no way back. Dragging a tab onto
another window's tab bar now moves it there, page and all, and the
right-click menu lists the other windows under Move to window. A
window whose last tab leaves closes.
2026-10-08 00:57:46 +02:00
Local Dev
4e41179d38 Theseus: sidebar and installed apps stay signed in across restarts
"Clear site storage on quit" wiped the IndexedDB and localStorage where
WhatsApp Web and Telegram Web keep their sessions, so both signed out at
every launch; only sites with a login in the vault were spared. The keep
list now also holds the sidebar web apps and the installed apps. The
switch sits under both clearing switches it applies to (it read as a
cookies-only option, indented under that one) and says what it covers.
2026-10-07 23:52:15 +02:00
Local Dev
110d0157de Theseus: sidebar panels open over the page or push it aside
An open sidebar panel (a web app or an extension panel) now has a bar on
top with its name, Maximize/Restore (it covers the page, up to the right
sidebar) and Close. How panels sit next to the page is a choice, in the
new gear above + on the strip and in Settings > Sidebar: over the page,
where it floats on the left of a page that keeps its width and a click in
the page closes it; or pushing the page aside, where it stays open until
closed. That choice replaces the pin, which only existed to keep a panel
open on a page click.

Also: a window laid out while minimized reads a zero-size area, so every
view was left at 0x0 and the window came back blank until resized.
Layout now skips a minimized window and runs again on restore.
2026-10-07 23:28:01 +02:00
Local Dev
f803491844 Theseus: move a tab to a new window
Right-click a tab and pick Move to new window, or drag it out of the tab
bar and let go off the window or over the page. The tab's own page moves
over, so sign-ins, scroll position and typed text stay as they were.

Each window has its own toolbar and tabs. The quick links, side panels
and sidebar stay in the first window and pass to another one if it
closes; the shared pop-ups (site info, downloads, password fill, page
dialogs, approvals) open in whichever window asks. Messages from a
window and events from its tabs run in that window's state, so the
existing single-window code keeps working. Closing a window's last tab
closes that window. The session file keeps every window with its place
on screen, and still opens in older builds as the first window.
2026-10-07 23:08:20 +02:00
Local Dev
e52907de01 Theseus: no unread counts on the taskbar icon
Any site could call navigator.setAppBadge(n) and Electron drew n over the
app's taskbar icon. Every site wrote the same single number, so the icon
showed a count with no way to tell whose it was. A session-wide preload now
removes the Badging API in pages and service workers, so sites fall back to
their own title or favicon counters.
2026-10-07 22:18:00 +02:00
Local Dev
de46b72764 Password manager and Theseus ID in the left sidebar's web apps
Quick links in the left sidebar (X, Telegram, WhatsApp, …) open in their own
panel, which is not a tab: it had no page preload, and the password manager
and Theseus ID accepted only tabs as senders. So a login typed there was
never offered for saving, a saved one was never offered for filling, and a
site that accepts Theseus ID answered "this page cannot use Theseus ID".

The panel now gets the same preload as a web tab (iframes included), and a
stand-in tab for it lets the existing offer, save, fill and sign-in code
treat it as one more tab-like place: offers show while the panel is open,
fill goes into the panel rather than the active tab, and the prompts it
raises are queued as no tab's, so they show over whichever tab is active.
2026-10-07 20:27:03 +02:00