Adds a provider row above Summary (dropdown mirroring Settings' AI
options + a local/hosted badge sourced from llm_status) so it's always
visible which provider a summary/tag generation will actually use.
Generate/Regenerate and the quick switch itself route hosted selections
(Anthropic, or "custom" once its endpoint resolves off-network) through
the same HostedAiBanner one-time acknowledgment gate as Settings — the
generate-click gate is the one that actually matters, since selecting a
provider alone sends nothing; it's kept even though the quick-switch
already pre-empts Anthropic specifically.
Also drops a stale svelte-ignore comment (pre-existing, unrelated to
this change — eslint-plugin-svelte no longer flags that element) that
was failing `eslint .` for this file.
Adds "Anthropic (Claude)" to the provider select, a write-only masked
API key field (show/hide toggle) shown in place of the endpoint field
for that provider (Anthropic's endpoint is fixed server-side), and a
persistent "leaves this device" note.
Save is gated behind HostedAiBanner the first time the user selects a
hosted provider (Anthropic, or "custom" once its endpoint resolves
off-network) and hasn't acknowledged hosted_ai_acknowledged yet;
accepting persists the ack and completes the save in one step.
New component mirroring ConsentNotice.svelte's card/overlay pattern:
shown before first use of a hosted (non-local) provider, explains that
the transcript leaves the device to a third party, and offers
accept/cancel. Uses the existing design tokens (--accent, --warning,
--bg-elevated, --radius-lg/sm, --shadow-lg) so it matches the
recording-consent notice visually. Not yet wired into any view — next
commits add it to Settings and SummaryPanel.
settings.svelte.ts's setLlmProvider now accepts an optional apiKey
(forwarded straight to the set_llm_provider command, which is the only
place it gets stored — the OS credential store) and DEFAULT_SETTINGS
gains hosted_ai_acknowledged. acknowledgeHostedAi() persists the
one-time hosted-AI banner acknowledgment the same way
acknowledgeConsent() does for recording consent.
New "MCP server" tab: persistent disclosure banner (agents may forward
served data to their own provider; WA itself adds no egress), enable
toggle, transport/port/scope controls, a reveal-once auth-token callout
(aria-live, never re-shown), and a live access-log list backed by the
settings store's mcp:// access subscription (FR-MCP-5).
Privacy tab gains a compact MCP status row + an explicit "adds nothing
to the egress list" confirmation line (FR-MCP-7, FR-SEC-2) next to the
existing sync/LLM egress rows.
Built with ui-ux-pro-max guidance (disclosure banner wording, reveal-
once secret pattern, aria-live for the token, badge semantics) mapped
onto this file's existing minimal/utilitarian style (banner/badge/row/
confirm classes already used by the Sync and Privacy sections) rather
than introducing a new visual language.
loadMcpStatus/loadMcpAccessLog/setMcpEnabled/setMcpScope mirror the
existing sync-target patterns; a live "mcp://access" subscription tails
the FR-MCP-5 audit log into the store while the panel is open, on top
of the on-demand loadMcpAccessLog() refresh. mcpLastToken holds the
freshly-minted token from the most recent enable, for the one-time
reveal UI (next commit).
Adds mcp_transport/mcp_port/mcp_expose/mcp_expose_recordings to
AppSettings and a typed McpStatus for mcp_status()'s response; types
onMcpAccess's payload correctly (the live event is camelCase per
docs/04-api-contracts.md, unlike the snake_case McpAccessEntry rows
mcpAccessLog() returns).
A <select> defaulting to "Default system audio", populated from the
enumerated render devices — picking one overrides which device
WhispAssist loopback-captures from instead of always following
Windows' system default.
Generate tags mirrors Generate summary: reads the transcript (the same
build_prompt assembly, non-streamed) and suggests 1-8 tags, merged
into the working tag list rather than replacing it outright so a
manually-added tag never silently disappears.
Replaces the old comma-separated text input with GitHub-topic-style
chips: typing a comma commits everything before it as its own chip
immediately, each chip is removable via its 'x', and clicking a chip's
label filters the meeting list to that tag (meetings.filterByTag).
Writable $derived instead of local $state, so clicking a tag chip
elsewhere (the Tags panel) is reflected here too, not just changes
made directly in this dropdown.
Same mechanism as the sidebar's tag dropdown (load with a tag filter,
drop search mode), just callable from anywhere a tag chip is clicked —
not only the dropdown itself.
Rounded pill using the existing --accent-soft/--accent tokens.
Clicking the label filters the meeting list to this tag; an optional
'x' removes it from whatever list rendered it (the component doesn't
know or care what "remove" means to its caller).
Nothing in the UI displayed or let you change a meeting's title
outside the sidebar list — recordings default to "Untitled meeting"
with no way to fix that. Adds an inline-editable header; blur/change
commits the rename.
attachEvent and renameMeeting can both change a meeting's title now, so
both refresh the list (not just the selected-detail view) to keep the
sidebar in sync.
A real mailbox import is thousands of events — searching/filtering
belongs where the user is actually tying a meeting to one, not just
the general browse list in Settings. Defaults the date filter to the
selected meeting's own recording date, since that's almost always the
event being linked.
Prefills the file path from settings once loaded (without clobbering
an in-progress browse/edit) and persists it after a successful import,
so the user doesn't have to re-browse to the same file every launch.
The new checkbox just flips pst_auto_sync, which lib.rs's one-shot
startup pass reads.
Tauri commands reject with a {kind, message} object, not a native Error,
so `e instanceof Error ? e.message : String(e)` always fell through to
String(e) -> "[object Object]", hiding the actual readpst failure reason.
Provider-aware Server URL placeholder/hint (Nextcloud/ownCloud: enter just the
server URL); Test in edit mode passes the target id so the backend reuses the
stored credential.
Each webdav target gets an Edit button that loads it into the form; save routes
to update_sync_target. Password left blank keeps the stored one; kind is locked
during edit. Fixes not being able to correct a mistyped Server URL.