Commit Graph

296 Commits

Author SHA1 Message Date
pewdiepie-archdaemon 127745d13b Email search: instant local-cache filter + stop blanking the grid
Two pain points:
- IMAP server search is genuinely slow.
- The grid blanked to a whirlpool on every keystroke, so even fast
  searches felt dead because you couldn't see your own results.

Fix:
- _localSearchFilter runs synchronously on every keystroke, filtering
  the pre-search snapshot by subject / from-name / from-address /
  snippet so the grid responds immediately. Snapshot is taken on the
  first non-empty keystroke and restored when the input is cleared.
- _doSearch no longer renders the loading-whirlpool spinner into the
  grid. The local filter already shows useful results; surface
  'Searching…' in the stats badge to indicate the server search is in
  flight.
- When server results land, they replace the grid; if the user has
  already typed past them, the seq guard skips the stale render.
2026-06-11 08:28:25 +09:00
pewdiepie-archdaemon 5ec1e12a50 Email bulk actions: loading state for every action + 6-way parallel fetches
Before: only delete showed a spinner/disabled buttons. Picking Done on
92 selected emails fired off 184 sequential HTTP calls (mark-answered
+ mark-read) with zero UI feedback, so it looked like the click did
nothing for the ~20-30 seconds it took to grind through.

- All five bulk actions (delete / archive / done / read / unread) now
  swap the target button into a whirlpool+verb-ing state, dim siblings,
  and show 'N/M…' progress in the count label that ticks as each
  request resolves.
- Per-uid work runs in parallel with a hard cap of 6 in flight, so a
  90-email Done finishes in ~3 server round-trips of latency instead
  of 90, but we still don't open 90 simultaneous IMAP-backed connections.
2026-06-11 07:41:36 +09:00
pewdiepie-archdaemon 7c1af0385a Email reader More menu: reorder + separators into three groups
Group 1 — per-email view actions:
  Open in new tab → Mark Unread/Read → Remind to reply
Group 2 — non-destructive state changes:
  Save sender to contacts → Done/Not Done → Archive
Group 3 — destructive (own divider):
  Move to Spam → Move to Trash → Delete Permanently

Adds support for { separator: true } items in the actions array,
rendered as .dropdown-divider rows.
2026-06-11 07:40:11 +09:00
pewdiepie-archdaemon dde2d25804 Email library bulk Done: animate-out + drop when filter='undone'
Repro: filter Undone → Select All → uncheck a few → Actions → Done →
nothing visible happens. Reason: the bulk-Done branch only flipped
em.is_answered on the in-memory entries; the cards stayed in
state._libEmails so they kept rendering, but now with the done check
ticked. From the user's POV — still 'undone' filter, cards still
there — it looked like the action was a no-op.

When the filter is 'undone' specifically, treat marking done as a
view-removal (same animate-then-prune step archive/delete uses).
2026-06-11 07:37:38 +09:00
pewdiepie-archdaemon 7f71fbc3ea Email list: scroll an expanded card into view after click
When clicking an email higher up in the list, its top edge can be hiding
behind the modal header or off-screen. After applying the
.email-card-expanded class + the new minHeight, scrollIntoView(block:start)
on the next animation frame so the user sees the whole card.
2026-06-11 07:35:32 +09:00
pewdiepie-archdaemon 7017127a11 Email card: drop redundant header kebab; keep bottom '...' menu in expanded state
The expanded email card painted a kebab menu in its title row because
the per-card .memory-item-actions menu at the bottom was hidden while
expanded. Both pointed at _showCardMenu(em). Remove the duplicate:

- Drop the email-card-header-menu button (and its rightCluster
  wrapper) — title row now just holds the nav arrows.
- Remove the CSS rule that hid .memory-item-actions on
  .email-card-expanded so the bottom kebab stays visible.
- Unread-dot insert point retargets to .email-card-nav-arrows now
  that the rightCluster is gone.
2026-06-11 07:33:04 +09:00
pewdiepie-archdaemon e25c279e4b Email Library: drop redundant 'All emails. Click to open as a document' subtitle 2026-06-11 07:28:21 +09:00
pewdiepie-archdaemon df54d8d2bf Email library: bulk 'Done' actually marks selected emails done
state._selectedUids holds whatever the server returns for em.uid (string
or number); the bulk action looped Array.from(...) and did strict ===
against state._libEmails entries. When the types disagreed, the find()
returned undefined, the in-memory is_answered flip never happened, and
the post-loop _renderGrid() painted the cards back into their original
not-done state — looking like 'mark done' did nothing even though the
server-side call had succeeded.

- Compare via String() on both sides so the in-memory state actually
  flips.
- Surface HTTP failure from mark-answered/mark-read so the existing
  failedReadSync toast can fire if the calls don't go through.
2026-06-11 07:27:25 +09:00
pewdiepie-archdaemon 9dbe31bfb0 Email/doc split: stop auto-tab-down when there's no room
Previously _prepareEmailWindowForDocument would:
  1. Check if there was horizontal room for both email + doc.
  2. If not, try collapsing the sidebar to recover space.
  3. If even that wasn't enough, _clearEmailDocumentSplit() — the
     email tab-down the user has been disliking.

Drop step 3. We still try collapsing the sidebar (free easy room),
but if the layout is still cramped, just dock anyway and let the
user manage their layout. _clearEmailDocumentSplit() is still
called on the legitimate close paths.
2026-06-11 07:17:26 +09:00
pewdiepie-archdaemon 2bf372b41c Tasks: optional persona for LLM + research tasks (biases output voice)
Wire the existing built-in PERSONAS catalog through to scheduled tasks
the same way I wired it to reminder synthesis. Repurposes the
dormant scheduled_tasks.character_id column.

UI (static/js/tasks.js)
- New 'Persona' select in the LLM / Research task form, with the five
  built-in characters (socrates/razor/nietzsche/spark/odysseus) plus a
  default 'no persona' option. Pre-populates from existing.character_id
  on edit. Non-llm/research types explicitly clear it on save.

API (routes/task_routes.py)
- TaskCreate + TaskUpdate gain character_id: Optional[str].
- _task_to_dict echoes character_id back so the form can hydrate on
  edit. Update endpoint stores '' as None to allow clearing.

Runner (src/task_scheduler.py)
- When task.character_id is set and matches a built-in persona, prepend
  the persona prompt to the task system prompt so the model speaks in
  that voice while still knowing it's running a scheduled task.
- crew_member.personality still wins as the base; character_id stacks
  on top.
2026-06-10 23:36:18 +09:00
pewdiepie-archdaemon a86990fc58 Email row: fix crash from leftover menu-wrap wiring after button removal
I removed the .email-menu-wrap markup from email rows earlier but
left the JS that queries it and calls .addEventListener on the
result. Since the query returns null, every _createEmailItem call
threw and the row never made it into the list — most visibly:
clicking a sender name to filter by them didn't appear to work,
because the row wiring (including the sender click handler) was
ripped out mid-construction.

- Drop the unconditional menuWrap.addEventListener('click', ...)
  block — there's no menu to open.
- Drop the early-return guard on touchstart that referenced the
  removed wrap.
- The two remaining .email-menu-wrap queries are already guarded
  with 'if (menuWrap)' so they safely no-op.
2026-06-10 23:31:23 +09:00
pewdiepie-archdaemon f4c1b264c6 Email reminder bell: re-evaluate visibility live on settings change
The bell is already gated on settings.reminder_channel === 'email', but
the check only ran at email-library init — so switching the reminder
channel in Settings didn't update the bell until you reopened Email.

- Settings/Reminders channel-change handler now dispatches
  odysseus-reminder-channel-changed { channel } after saving.
- emailLibrary listens for it and re-runs _syncEmailReminderBellVisibility
  with the new channel value.
2026-06-10 23:26:53 +09:00
pewdiepie-archdaemon 031a600725 Email accounts strip: drop redundant 'Accounts' label during load — whirlpool alone
The strip already lives where account chips render, so the text label
beside the whirlpool was redundant. Strip the label + the fallback
'Accounts...' text — the spinner alone tells the user accounts are
loading.
2026-06-10 23:22:59 +09:00
pewdiepie-archdaemon b385b25d5f Email row: remove the three-dot actions menu button
Dropped the .email-menu-wrap / .email-menu-btn from each row. Other
handlers that check 'if (e.target.closest(.email-menu-wrap)) return;'
safely no-op when the element doesn't exist. Row click + swipe still
open the email and its in-reader actions.
2026-06-10 23:21:17 +09:00
pewdiepie-archdaemon 49b72bd09c Email attachments: nudge download spinner up 2px to sit on icon baseline 2026-06-10 23:19:19 +09:00
pewdiepie-archdaemon 0a3333b961 Edge-dock resize handle: fade accent stripe in on hover
Transparent at rest, accent gradient animates in on hover with a 0.18s
ease transition. Drag affordance + col-resize cursor still work; the
stripe just stops bothering you when not touched.

Right-side handle mirrors the gradient direction (left-to-right
gradient flipped to right-to-left).
2026-06-10 23:18:07 +09:00
pewdiepie-archdaemon cd9ad1a7f2 Email attachments: swap paperclip for whirlpool spinner during download
Before: the attachment chip just dimmed (opacity 0.6) while the file
downloaded — easy to miss on a large attachment.

Now: replace the paperclip SVG with a 12px whirlpool spinner for the
duration of the fetch, restoring the original icon when the download
finishes (or errors out). Same loading vocabulary as Test / Scan /
Probe / Send buttons elsewhere in the UI.
2026-06-10 23:15:52 +09:00
pewdiepie-archdaemon 023f1ba575 Email inbox: visual flash when an email is auto-marked done after sending
When the email-answered event fires (user just sent a reply, so the
source email auto-marks as done), the row was getting the .active
class instantly with no visible cue beyond the checkbox tick. Add a
brief .email-auto-done-flash class on the row that runs two keyframe
animations:
- email-auto-done-row: tints the row background with the accent for
  ~1.2s then fades to transparent.
- email-auto-done-check: pops the done checkbox to 1.4× with an
  accent ring that expands outward over 0.6s.

Class self-removes after 1.2s so it doesn't replay on re-renders.
2026-06-10 23:06:42 +09:00
pewdiepie-archdaemon 1a4659b7fc Edge-dock resize handle: drop the visible accent stripe
The drag handle painted a 35% accent gradient strip on the page edge
of any docked panel. The col-resize cursor on hover is enough to
surface the affordance; the stripe felt like a stray UI element.
2026-06-10 23:05:39 +09:00
pewdiepie-archdaemon 965b0e143c Email accounts strip: wheel + grab-drag horizontal scroll
The single-row chip strip relied on native horizontal scroll, which is
hard to reach without a horizontal wheel. Wire two scroll mechanisms
on the strip once it's rendered:

- Vertical wheel → horizontal scroll (intercept only when overflow
  exists and the wheel motion is primarily vertical, so normal page
  scroll still works elsewhere).
- Mouse grab-and-drag: cursor goes grab/grabbing, mousedown→move
  bumps scrollLeft by the cursor delta. A 5px drag threshold cancels
  the chip click so the user can drag-scroll without accidentally
  switching accounts.
2026-06-10 23:00:29 +09:00
pewdiepie-archdaemon 1eca28e588 Email: revert single-row email-item; account chips single-row at all widths
- Revert the email row layout — sender/date stay above subject again,
  matching the original two-line item that the user actually wanted.
- The account filter chips (#email-lib-accounts) wrapped onto multiple
  rows on desktop. Promote the mobile-only horizontal-scroll rule to
  apply at every breakpoint so the chips always sit on one row with
  overflow scroll, regardless of screen size.
2026-06-10 22:55:10 +09:00
pewdiepie-archdaemon 89efd7d44b Email list: collapse to a single row — [sender] [subject] [date]
Subject was on its own line below sender/date. Move it inline so each
email occupies one row: sender capped at 35% width (ellipsis), subject
takes the remaining space (ellipsis), date pins to the right. Tighter
list density at the cost of dropping the spare line for snippet text
(none was being rendered anyway).
2026-06-10 22:45:19 +09:00
pewdiepie-archdaemon 1ee51be420 Sessions: Esc + outside-click also close the Move-to-folder submenu
The session-dropdown Esc handler only closed .session-dropdown-menu,
leaving the .session-folder-submenu (Move to folder → folder list)
orphaned on screen. Same gap on the click-away path. Extend both
selectors to cover the submenu so a single Esc / outside-click
dismisses the whole stack.
2026-06-10 22:39:23 +09:00
pewdiepie-archdaemon 4f7061fd61 Settings overhaul + UI polish pass
Two months of iteration on the Settings panel, integration forms, and
small visual nudges across the app. Highlights:

Settings restructure
- Add Models: split into separate Local + API cards (no more in-card
  tabs); each fuses Type/Provider with the URL input.
- Added Models: new dedicated sidebar tab, with Probe + Clear-offline
  pulled into its header; Local/API sub-section icons accent-tinted.
- Search: Web Search and a new Deep Research card (Model + tuning),
  with a cross-link to AI Defaults. Provider hints use real clickable
  anchors; Web Search Test button shows a whirlpool spinner.
- AI Defaults: Image Generation card returns; Research Model card
  carries only Endpoint+Model with a cross-link to Search; Vision /
  Default / Utility fallbacks unified under one numbered-row design
  matching Search's chain.
- API Permissions (was 'API Tokens'): per-row rename, inline
  Permissions toggle that expands the scope-edit panel, in-field
  copy icons (icon→check on success). Empty state accent-tinted.
- Integrations: + Add Integration drops a type-picker menu directly
  under the button (drop-up on tight viewports); each integration
  form (API, CalDAV, CardDAV, Email, Codex/Claude, Vault, MCP) uses
  the same accent-outlined Save/Test/Cancel buttons right-aligned.
- Danger Zone: Wipe→Delete with trash icons; new 'Delete everything'
  row at the bottom that loops every category.

AI Synthesis (Reminders)
- Persona dropdown sourced from PROMPT_TEMPLATES + custom preset.
- src/reminder_personas.py mirrors the five built-ins for the
  server-side synthesis path.
- dispatch_reminder() reads reminder_llm_persona and uses the
  persona's system prompt; empty/unknown falls back to warm-neutral.

Esc handling
- Kebab menus and the provider picker intercept Esc in capture phase
  so dismissing a popup no longer closes the whole Settings modal.

Accent tinting
- Scoped CSS rule across data-settings-panel=ai/services/added-models/
  search/integrations/reminders for card h2 icons + the Added Models
  sub-section icons.

Codex/Claude integration form
- No more auto-creation on form open — explicit Create token button.
- New tokens start with every scope granted; existing tokens move out
  of the integration form into the API Permissions card.
- Setup reveal: copy buttons inline inside the token + setup code
  blocks; shorter subtitle wording.

Misc visual polish
- Save/Test/Cancel uniformly accent-outlined and right-aligned on
  every integration form.
- Provider logos render inline next to the search fallback selects
  and the Deep Research Search dropdown.
- Trash icons in fallback rows bumped to 20x20 so they fill the 32px
  button.
- Image generation default flipped to off.
2026-06-10 15:15:13 +09:00
pewdiepie-archdaemon b2458f9891 Settings/Add Models: split Local and API into separate cards, always show API key
Drop the in-card Local/API tab strip — each is now its own admin card with
a normal h2 heading (Local on top, API below). The API key input is
always visible (no more click-to-reveal toggle), matching how cloud
providers actually work. Local keeps the optional key reveal since
local servers usually don't need one.

Dead code removed: wireModelsTabs IIFE and the adm-epApiKeyBtn toggle wire.
2026-06-09 14:57:42 +09:00
pewdiepie-archdaemon 2252776a97 Settings: promote Added Models to its own sidebar menu
Move the Added Models endpoint lists out of the Add Models card into a
dedicated sidebar tab between Add Models and AI Defaults. The card now
focuses purely on adding (Local / API tabs), while the new panel owns
the existing endpoints + Probe and Clear-offline controls.

admin.js: defensive fallback so a stale 'added' value in localStorage
falls back to 'local' instead of leaving both panes hidden.
2026-06-09 14:52:48 +09:00
pewdiepie-archdaemon 75268e7f43 Fix Cookbook serve server selection 2026-06-09 14:45:22 +09:00
pewdiepie-archdaemon 8ef9b8b215 Settings: tabbed Add Models card with Local / API tabs
Earlier split into 4 flat cards wasn't what was asked for. Restore to
a single 'Add Models' card with two tabs at the top:

  Local  → Add form + Added Local Models list
  API    → Add form + Added API Endpoints list

Probe / Clear-offline live on the card header and act on both lists.
Active tab is remembered in localStorage so the user lands back where
they were. All form/list IDs preserved (adm-epLocalUrl, adm-epList-local,
adm-epList-api, etc.) so admin.js continues to work unchanged.

Replaces the .adm-section-toggle fold-open JS with a tab-switcher; the
fold elements no longer exist so the old handler was already a no-op.
2026-06-09 14:43:28 +09:00
pewdiepie-archdaemon d397b3db2f Restore dropped regression fixes 2026-06-09 10:31:43 +09:00
pewdiepie-archdaemon 6f29b287f6 Remove stale plan slash toggle 2026-06-09 09:54:46 +09:00
pewdiepie-archdaemon 4715a5505d Fix duplicate cookbook server helper export 2026-06-09 09:53:41 +09:00
pewdiepie-archdaemon 84ca74f04b Restore cookbook server key exports 2026-06-09 09:51:53 +09:00
pewdiepie-archdaemon e6b1009b89 Remove non-merge-ready workspace and terminal agent hooks 2026-06-09 09:48:59 +09:00
pewdiepie-archdaemon fa8c93ec0a Cookbook UI: Ollama browser, advanced serve fold, API tokens form, diagnosis toolbar, polish
Surface a lot of accumulated cookbook + UI work as a single non-agent
commit so the agent rework lands cleanly.

Highlights:
- Ollama as a first-class backend in the Cookbook:
  * Download input accepts ollama-style names (name:tag) → backend=ollama
  * /api/cookbook/ollama/library (cached scrape of ollama.com + curated
    fallback so classic models like qwen2.5 stay reachable)
  * "Browse Ollama library" toggle below Download with size chips
  * Engine=Ollama in hwfit toolbar merges the Ollama library into the
    main scan list as per-tag rows with the same Fit/Param/Quant/VRAM
    columns; click → fills Download input
- API Tokens form added to Integrations panel (matching wired
  loadTokens()/initTokenForm() that had no HTML)
- Serve panel polish: Advanced fold tightening (-8px nudges on vLLM
  checks, Extra args, Spec row), n_cpu_moe + Split Mode controls
  pulled up 8px to align with the row's checkboxes, GGUF File dropdown
  exposed for Ollama backend, GPU re-render on Edit serve restore,
  _forceBackend flag so saved serveState wins over backend detection,
  cookbook:servers-changed CustomEvent so panels don't need refresh
- Models page redesign: Add Models row (URL + hidden API key reveal +
  Type select + Scan/Ollama/Key/Test/Add icon buttons), Probe All +
  Clear-offline buttons in Added Models toolbar, offline-pill removed
  (opacity already conveys state), Engine dropdown gains Ollama option
- _ping_endpoint probes /v1/models then base, accepts 4xx as
  reachable (vLLM returns 404 on bare /v1, fully working endpoints
  were showing offline)
- Diagnosis card: × dismiss + Copy bundle buttons restored on the
  serve error feedback card
- Orphan tmux sweep re-enabled behind a 60s rate-limit + background
  Thread (off the main event loop) so dead serves get discovered
- cookbook_routes auto-register watchdog: drops the endpoint if the
  serve session exits non-zero within the first ~3min
- ollama-rocm sidecar awareness in download wrapper (`docker exec
  ollama-rocm ollama pull` when host ollama isn't installed)
- Skill extractor sets initial_status="published" when
  auto_approve_skills pref is on (audit demotes later)
- Skill list / model list / cookbook scan misc polish
2026-06-09 09:46:19 +09:00
pewdiepie-archdaemon 646f8bd2a9 Remove remaining plan mode frontend code 2026-06-09 09:44:22 +09:00
pewdiepie-archdaemon 2a2a93d845 Remove plan mode from merge-ready UI 2026-06-09 09:40:20 +09:00
pewdiepie-archdaemon 3b01760e95 Prepare tested main sync cleanup 2026-06-09 09:34:42 +09:00
Ocean Bennett 62ffcb6236 fix(cookbook): preserve same-host ssh profile selection (#3373)
* fix(cookbook): preserve same-host ssh profile selection

* fix(cookbook): resolve same-host ssh profiles in running tab and port lookups
2026-06-09 00:36:10 +02:00
Lucas Daniel 5462030cde fix(auth): per-user allowed-models checklist ignores cache, [None] doesn't block (#3355)
Three issues combined to make the per-user 'Allowed models' checklist
unreliable (#3032):

1. admin.js _loadModelsForUser fetched /api/models, which is backed by
   cached_models — endpoints that haven't been probed yet (e.g. a
   freshly-added DeepSeek API endpoint) simply didn't show up in the
   checklist. Switched to /api/model-endpoints, which always reflects
   every configured endpoint regardless of cache state.

2. _saveModels sent allowed_models: [] both when the admin clicked
   [All] (no restriction) and [None] (block everything) — the backend
   had no way to distinguish the two.

3. _enforce_chat_privileges treated an empty allowed_models list as
   'no restriction' (falsy -> skip the check), so [None] had no effect.

Added an explicit block_all_models privilege flag (defaulting to False,
and forced to False for admins) that admin.js now sets when zero models
are checked. _enforce_chat_privileges checks it first and 403s
regardless of allowed_models contents.
2026-06-08 22:52:39 +02:00
Aman Tewary d458cade98 docs(email): clarify Outlook password auth failures
Co-authored-by: Alexandre Teixeira <111787685+alteixeira20@users.noreply.github.com>
2026-06-08 15:32:16 +01:00
PewDiePie fe19d072e3 Revert "fix: expose supports_tools toggle for local endpoints in UI (#3195)" (#3438)
This reverts commit 7b68413433.

Co-authored-by: pewdiepie-archdaemon <pewdiepie-archdaemon@users.noreply.github.com>
Co-authored-by: Kenny Van de Maele <kenny@kvandemaele.be>
2026-06-08 14:46:01 +02:00
PewDiePie 09565acc1e Revert "feat(model-picker): add remove-from-recent button to Recent section rows (#2894)" (#3437)
This reverts commit 2a422c00ec.

Co-authored-by: pewdiepie-archdaemon <pewdiepie-archdaemon@users.noreply.github.com>
2026-06-08 14:41:25 +02:00
Mostafa Eid d6882a895e feat(chat): recall last user message on empty composer ArrowUp (#1175)
Pressing ArrowUp on an empty #message composer restores the last sent user text, matching common chat-app UX (Slack, Discord, ChatGPT).

- Read from #chat-history .msg-user dataset.raw (same path as resend/regenerate), not session sidebar metadata

- Literal empty check (whitespace-only drafts are preserved); ignore Shift/Alt/Ctrl/Meta and IME composition

- Extract wiring to composerArrowUpRecall.js; rAF + 250ms retry only (no global MutationObserver)

- Add tests/test_composer_arrow_up_recall_js.py

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 13:06:05 +02:00
stocky789 1e0d9b92af feat: add ChatGPT Subscription provider (#2876)
* feat: Add ChatGPT Subscription support and related features

- Introduced a new provider option for ChatGPT Subscription in the endpoint selection UI.
- Implemented OAuth flow for ChatGPT Subscription sign-in, including polling for authorization status.
- Updated admin interface to handle ChatGPT Subscription, including disabling API key input and providing user guidance.
- Enhanced cost tracking logic to differentiate between subscription and non-subscription endpoints.
- Added new slash commands for managing skills, including listing, searching, and invoking skills.
- Implemented caching for skill catalog to optimize performance.
- Updated tests to cover new ChatGPT Subscription functionality and ensure proper endpoint probing.
- Refactored existing code to accommodate new features and improve maintainability.

* refactor: share provider device-flow setup

- reuse one device-flow backend for Copilot and ChatGPT Subscription
- add one frontend device-flow helper for Settings and /setup
- put GitHub Copilot back into Add Models, now as a dropdown option
- make provider selection just select; clicking Add starts sign-in
- stop ChatGPT Subscription setup from opening auth tabs automatically
- make /setup copilot and /setup chatgpt-subscription work from chat
- show ChatGPT Subscription in the /setup suggestions
- show the real error message when setup fails
- add focused tests for the shared flow and setup UI

* feat(chatgpt-subscription): harden credential lifecycle and streamline auth UX

Backend:
- Resolve runtime bearer for provider-auth endpoints at probe time via a
  shared _resolve_probe_key() that delegates to resolve_endpoint_runtime,
  applied across all probe/refresh call sites.
- Skip live completion probes and health pings for discovery-only providers
  (centralized behind _is_discovery_only_provider) — the Codex/Responses API
  has no such endpoints, so status is derived from cached models.
- Never persist the short lived ChatGPT bearer to the plaintext sessions
  table; proactively clear any stale bearer left by an earlier code path.
- Revoke orphaned ProviderAuthSession credentials when the last endpoint
  backing them is deleted (_delete_orphaned_provider_auth), surfaced via
  cleared_provider_auth in the delete response.

Frontend (admin.js):
- Auto-start the device-auth flow on provider selection so the authorization
  panel (code + Authorize) shows immediately instead of behind a "Sign in" click.
- Remove the redundant top button for device auth providers, move retry
  into the panel via an inline "Try again".
- Drop the self-evident hint text and add an execCommand clipboard fallback so
  Copy works in non-secure (HTTP/LAN) contexts.

* fix: harden chatgpt subscription provider

* chore: remove PR media from branch

* Fix chatgpt subscription recovery and token handling

---------

Co-authored-by: 5p00kyy <admin@5p00ky.dev>
2026-06-08 10:19:18 +02:00
michaelxer 7b68413433 fix: expose supports_tools toggle for local endpoints in UI (#3195)
* fix: expose supports_tools toggle for local endpoints in UI

Local endpoints (Ollama, vLLM, etc.) default to fenced tool blocks
when supports_tools is not set, which breaks tool calling for models
that support native function calling. The backend already supports
per-endpoint supports_tools overrides via the PATCH API, but there
was no UI to set it.

Add a 'Tools: Auto/On/Off' toggle button for local endpoints that
cycles through the three states:
- Auto (null): use the existing heuristic
- On (true): always use native function calling
- Off (false): always use fenced tool blocks

Fixes #3141

* docs: add screenshot of supports_tools toggle showing Auto/On/Off states

* Add Tools toggle screenshot for PR #3195

* refactor: convert Tools toggle to select dropdown per review feedback

Replace cycle-through button with a <select> dropdown for the
supports_tools tri-state setting. Options: Auto / On / Off with
explicit labels. Uses existing admin select styling. Fires PATCH
on change event. Same API contract (Auto=null, On=true, Off=false).

* Update Tools toggle screenshot (now dropdown select)

* fix: remove orphan screenshot and move Tools dropdown below button row

- Remove docs/screenshots/tools-toggle-three-states.png (unreferenced image causing test_no_orphan_images_in_docs to fail)
- Move Tools dropdown to its own line below Disable/Delete buttons, aligned right
- Keep Disable and Delete buttons grouped together per maintainer feedback

* fix: move Tools select onto same row left of Disable/Delete, use CSS class

Per vdmkenny feedback: move the Tools dropdown select from its own row below
the button group onto the same row, to the left of the Disable and Delete
buttons (which stay adjacent on the right). Replace inline style on the
button row with the existing .admin-ep-actions CSS class, adding
align-items:center for proper vertical alignment.

* chore: remove committed screenshots from tree

Screenshots should be in PR description/comments, not in repo history.

---------

Co-authored-by: michaelxer <michaelxer@users.noreply.github.com>
2026-06-08 00:29:06 +02:00
nubs 8746c9c0df fix(documents): discard pending AI diff before switching active doc (#2484)
The document editor stores the AI-edit diff state (_diffModeActive,
_diffOldContent, _diffNewContent, _diffChunks) as a module-global
singleton bound to whatever document was active when the diff opened,
and every document shares one #doc-editor-textarea. When the active
document is switched while an unapproved diff is open, the stale diff
must be discarded first or a later exitDiffMode (tab switch /
Accept-Reject-All) flushes the old document's content into the new
active document and overwrites it (issue #2467).

Guard both paths that switch the active document for an AI update,
while activeDocId still points at the previously-active doc:
- handleDocUpdate(): a doc_update targeting a different document.
- streamDocOpen(): the AI streaming a NEW document — this runs first on
  that path, so a guard only in handleDocUpdate would fire too late and
  still overwrite the streamed document.

Both reuse the exact `if (_diffModeActive) exitDiffMode(true);` guard
switchToDoc() and enterDiffMode() already use.

Fixes #2467
2026-06-07 22:35:35 +02:00
nubs f7c0b3f23b fix document preview refresh after AI edits (#2259) 2026-06-07 22:33:01 +02:00
lekt8 accdc4fc53 Add hover tooltips for clipped model names (#1982) (#1985)
Long model names are truncated with ellipsis in two places with no way to see
the full name: the model-picker dropdown items and the chat-header model
indicator. Add a native title tooltip carrying the full name to both — the
dropdown item's name span (nameSpan.title = m.display) and the header label
(label.title = the full model id; empty for the 'Select model' placeholder).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 19:23:44 +02:00
michaelxer d7ece5b4a9 fix: show backend error detail in context-popup compact button (#2721)
When the context-popup compact button receives a non-OK response (e.g.
409 for active-run), the error detail from the backend was being
discarded in favor of a generic 'Compaction failed' message.

Now parses the JSON response body for non-OK responses and prefers the
detail field when present, matching the behavior of the /compact slash
command. Uses textContent for safe rendering.

Co-authored-by: michaelxer <michaelxer@users.noreply.github.com>
2026-06-07 18:16:58 +02:00
Zen0-99 2a422c00ec feat(model-picker): add remove-from-recent button to Recent section rows (#2894)
* feat(model-picker): add remove-from-recent button to Recent section rows

* fix(model-picker): restore original browse-mode section logic, keep remove button only
2026-06-07 17:45:59 +02:00