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.
list_audio_devices runs the (blocking, COM-based) enumeration off the
async runtime via spawn_blocking, same pattern as import_pst_core.
start_recording now passes settings.audio_output_device through to
WasapiCapture::start instead of always capturing the default device.
Device::get_id() string; None = system default (unchanged behavior).
#[serde(default)] so an existing settings.json without this key still
deserializes.
AudioCapture::start now takes an optional device id (Device::get_id())
instead of always resolving the system default render device.
open_capture_session/find_render_device resolve the configured device,
falling back to the system default if it's no longer present (same
degrade-gracefully spirit as the existing mid-recording reconnect,
which now retries the *same* selection rather than switching to
whatever's currently default).
Adds list_render_devices() (new AudioDeviceInfo) for the Settings
picker — enumeration was already fully supported by the wasapi crate,
just unused until now.
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).
Non-streaming — a 1-8 tag reply is short enough that a second
token-stream event isn't worth wiring up. Implemented for Ollama and
the OpenAI-compatible path (reusing summarize()'s SSE plumbing, just
accumulating instead of forwarding to a TokenSink); the Anthropic stub
mirrors its existing "not built yet" summarize() error.
parse_tags/sanitize_tag/strip_ordinal_prefix handle a model that
ignores "comma-separated, nothing else" (numbered lists, newlines,
quotes) and normalize everything to lowercase, hyphenated, chip-safe
tags, capped at 8 and deduped.
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.
rename_meeting backs a user-editable title (T2.2) — recordings had no
way to change their default "Untitled meeting" name from the UI at all.
attach_meeting_to_event now also copies the linked event's subject onto
the meeting's title when it has one: linking is meant to say "this
recording is that meeting," so the title should follow.