Commit Graph
253 Commits
Author SHA1 Message Date
iamdoubz ea79fb656d docs(commands): correct playback requirement id to FR-REC-5 2026-07-06 17:56:16 -05:00
iamdoubz a7eba7fd82 build: lockfile for tauri protocol-asset (http-range) 2026-07-06 17:55:13 -05:00
iamdoubz 010941e620 feat: enable asset protocol + media-src CSP for recording playback 2026-07-06 17:52:00 -05:00
iamdoubz 90580da0af build: enable tauri protocol-asset feature for recording playback 2026-07-06 17:51:59 -05:00
iamdoubz e715c09ce0 feat: register cancel_recording + recording_playback_path commands 2026-07-06 17:51:58 -05:00
iamdoubz da25ccaec6 feat: cancel_recording, recording_playback_path, live sync progress 2026-07-06 17:51:57 -05:00
iamdoubz e7f628ad7a feat(sync): stream upload bodies with live byte progress (FR-SYNC-11) 2026-07-06 17:51:55 -05:00
iamdoubz 25d0232256 feat(vault): add is_sealed() helper 2026-07-06 17:51:54 -05:00
iamdoubz 34b4f4ae09 feat(audio): write recordings as 16-bit PCM to halve .wav size (FR-CAP-8) 2026-07-06 17:51:53 -05:00
iamdoubz 4cdeb8f475 test(audio): real-hardware microphone open/stop smoke test (FR-CAP-7) 2026-07-06 16:29:56 -05:00
iamdoubz 97b5f67049 feat(audio): wire mic capture + mixer into recording lifecycle (FR-CAP-7) 2026-07-06 16:26:17 -05:00
iamdoubz 55ddaad544 feat(audio): track mic capture handle; register list_input_devices (FR-CAP-7) 2026-07-06 16:26:16 -05:00
iamdoubz 75f7d19ade feat(audio): add microphone_enabled + audio_input_device settings (FR-CAP-7) 2026-07-06 16:26:14 -05:00
iamdoubz 2fb5fd6f30 feat(audio): microphone capture + stream mixer (FR-CAP-7) 2026-07-06 16:26:13 -05:00
iamdoubz 5b281531fb feat(audio): register list_audio_devices with the Tauri invoke handler 2026-07-06 16:00:50 -05:00
iamdoubz 2759a0e49a feat(audio): add list_audio_devices command; wire device into start_recording
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.
2026-07-06 16:00:49 -05:00
iamdoubz 8e3e22c0e5 feat(audio): add audio_output_device to Settings
Device::get_id() string; None = system default (unchanged behavior).
#[serde(default)] so an existing settings.json without this key still
deserializes.
2026-07-06 16:00:47 -05:00
iamdoubz bb1d1730f8 feat(audio): device-selectable WASAPI loopback capture
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.
2026-07-06 16:00:46 -05:00
iamdoubz ba1b577734 feat(llm): register generate_tags with the Tauri invoke handler 2026-07-06 15:38:01 -05:00
iamdoubz fb406d62da feat(llm): add generate_tags command
Reuses build_prompt's transcript+metadata assembly (same as
generate_summary) and the same recording-in-progress guard.
2026-07-06 15:38:00 -05:00
iamdoubz 68c32ffa06 feat(llm): add suggest_tags to LlmProvider for AI-generated tags
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.
2026-07-06 15:37:59 -05:00
iamdoubz ae9e8398c5 feat(meetings): register rename_meeting with the Tauri invoke handler 2026-07-06 15:10:55 -05:00
iamdoubz 4f80c14f72 feat(meetings): add rename_meeting command
Validates a non-empty trimmed title before delegating to the store.
2026-07-06 15:10:54 -05:00
iamdoubz e68e888c07 feat(meetings): rename_meeting + mirror event subject on attach
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.
2026-07-06 15:10:53 -05:00
iamdoubz 9d757be415 feat(calendar): one-shot PST auto-sync on launch
Mirrors the existing sync-job-resume pattern right above it: runs once
at startup if pst_auto_sync is on and a path is remembered, no idle
timer (NFR-RES-1). Re-import is dedup'd by (source, raw_uid), so this
just catches up on new/changed events since last launch.
2026-07-06 14:55:36 -05:00
iamdoubz 871b11d75e refactor(calendar): split import_pst into a reusable core fn
import_pst_core takes &AppHandle/&dyn Store directly instead of the
State<AppState> extractor, so the startup auto-sync pass (lib.rs) can
run the same import logic without going through a Tauri command.
2026-07-06 14:55:34 -05:00
iamdoubz 75ec24ddf6 feat(calendar): add pst_last_path/pst_auto_sync to Settings
Backing fields for remembering the imported .pst path across sessions
and an opt-in startup auto-resync (T6.2). #[serde(default)] so an
existing settings.json without these keys still deserializes.
2026-07-06 14:55:33 -05:00
iamdoubz 4637ce8aac chore(deps): promote chrono to a direct dependency
Needed for DST-aware recurrence expansion (calendar/mod.rs); already
resolved transitively via sqlx, so this adds no new compiled crate.
2026-07-06 14:55:31 -05:00
iamdoubz 6f07f28cef fix(calendar): preserve local wall-clock time across DST in recurrence
expand_rrule reused dtstart's raw UTC time-of-day for every occurrence,
so a weekly meeting spanning a DST transition (e.g. created in winter
CST, recurring into summer CDT) drifted an hour once displayed in the
machine's local timezone.

Rewrites occurrence generation on chrono's Local/NaiveDate (already a
transitive dependency via sqlx, now promoted to direct) instead of
hand-rolled epoch-day arithmetic: each occurrence keeps dtstart's local
wall-clock hour/minute, re-resolving the UTC offset per occurrence date
so DST is applied correctly for that specific day. civil_from_days/
weekday_from_epoch_day/is_leap_year/days_in_month are no longer needed
(chrono's NaiveDate replaces them) and are removed.
2026-07-06 14:55:30 -05:00
iamdoubz fa8a7f2552 feat(calendar): expand recurring PST events into per-occurrence rows
RRULE was previously ignored entirely, so a recurring meeting only ever
stored its first occurrence — invisible to any later date filter/lookup.
Adds RRULE parsing + occurrence expansion (DAILY/WEEKLY/MONTHLY/YEARLY,
INTERVAL/COUNT/UNTIL/BYDAY/BYMONTHDAY/BYMONTH) covering every pattern
found in a real 7.2GB mailbox (ADR-0008), each occurrence stored as its
own row keyed by "{uid}@{ymd}" so re-import dedup still applies.

Also fixes a real parser bug found via that mailbox: this libpst build
joins multi-value BYDAY with `;` instead of RFC 5545's `,`
(BYDAY=MO;TU;WE;TH;FR), which previously made RRULE parsing bail out
silently for any event with more than one weekday.

Indefinite rules (no COUNT/UNTIL — only YEARLY holidays in practice) are
capped at 10 years/500 occurrences; ponytail-flagged as the ceiling to
raise if a real series needs more.
2026-07-06 14:34:21 -05:00
iamdoubz 2ca4151444 fix(calendar): fall back to stdout when readpst's stderr is empty
readpst writes some failure messages to stdout rather than stderr, so a
failing run with empty stderr surfaced as a blank "parse failed: " error
with no diagnostic content.
2026-07-06 13:56:44 -05:00
iamdoubz 6a4b832628 chore(release): bump version to 0.1.6 2026-07-06 13:08:41 -05:00
iamdoubz 33c0397de8 fix(sync): enable keyring windows-native backend — creds were a silent no-op
keyring 3.x feature-gates its OS backends OFF by default, so with no feature the
credential store fell back to a mock where set/get don't share state: every
password write appeared to succeed but read back empty, so no Basic auth was
sent and WebDAV/Nextcloud auth always 401'd. windows-native pulls the real
Windows Credential Manager. Also affected MCP/hosted-AI keys + OAuth tokens.
2026-07-06 13:08:39 -05:00
iamdoubz 8f6e8041d6 feat(sync): auto-build Nextcloud/ownCloud DAV path from the server URL
For nextcloud/owncloud, WebDavTarget now derives the canonical
…/remote.php/dav/files/<user>/ path from the entered server URL (origin only, so
a pasted full path normalizes too); other providers use the URL verbatim.
test_sync_target also reuses the stored password when editing an existing
webdav target (unless a new one is typed), so Test works after a URL fix without
re-entering the password. Fixes the confusing 'bare host connects, full URL
fails' behavior (the former was a 404 false-positive, the latter a blank-secret
401).
2026-07-06 11:10:44 -05:00
iamdoubz 149f2c995d feat(sync): expose upload flags in SyncTargetInfo for the edit form
row_to_info now returns upload_transcript/notes/summary/recording,
trigger_on_finalize, allow_plaintext_lan, encrypt_before_upload so the UI can
pre-fill an edit form accurately (still never the secret, FR-SYNC-6).
2026-07-06 10:40:57 -05:00
iamdoubz 224aaf9994 fix(runtime): use gitea /media/ URLs so Git LFS bundles resolve (not the pointer) 2026-07-06 09:45:01 -05:00
iamdoubz e6f19168f8 feat(runtime): download NPU/DirectML runtimes as 7z from the repo raw URLs
extract_7z_flat replaces extract_zip_flat; NPU + DirectML now default to
git.dou.bet raw/branch/main/runtime/{openvino,directml}.7z with pinned SHA-256s
(DirectML no longer requires WA_DIRECTML_RUNTIME_URL). Adds an extraction test
against the real bundle (proves LZMA2+BCJ decode + flatten).
2026-07-06 08:23:49 -05:00
iamdoubz 27ba4f9b03 build(deps): swap zip for sevenz-rust2 (npu-gated) to unpack 7z runtime bundles
The NPU/DirectML runtime bundles are now LZMA2+BCJ 7z archives; zip was only used
for the old .zip bundle. sevenz-rust2 pinned to 0.7.0 (newer needs rustc>MSRV).
2026-07-06 08:23:49 -05:00
iamdoubz 0d62416127 chore(release): bump version to 0.1.5 2026-07-06 07:46:29 -05:00
iamdoubz 42c2aedfd4 feat(commands): register app_info + open_url 2026-07-06 07:46:18 -05:00
iamdoubz 0317649b48 feat(commands): app_info (version+commit) and open_url for the About page 2026-07-06 07:46:18 -05:00
iamdoubz 035abb93ea build: bake short git commit hash into WA_GIT_HASH for the About page 2026-07-06 07:46:17 -05:00
iamdoubz ceb7e59164 feat(commands): expose directml.applicable in hardware_status (P2) 2026-07-06 07:21:50 -05:00
iamdoubz 281ccf0b18 feat(hardware): directml_would_help() gate for the Settings package card (P2)
True only when staging DirectML would light up a present GPU this build can't
otherwise accelerate: npu compiled, no Vulkan baked in, and an AMD/Intel GPU
present (or NVIDIA without CUDA).
2026-07-06 07:21:50 -05:00
iamdoubz ab5aa4e986 feat(commands): register download_directml_package command (P2) 2026-07-05 19:40:28 -05:00
iamdoubz b69c91a598 feat(commands): route AMD/Intel to DirectML ONNX engine + download_directml_package (P2)
load_transcriber dispatches OnnxOpenVino/OnnxDirectML through one OnnxTranscriber
block. download_and_extract_runtime is parameterized (sha + readiness) so the new
stage_directml_runtime reuses it; hardware_status reports a directml package field.
2026-07-05 19:40:27 -05:00
iamdoubz 0f2940e52b feat(hardware): make directml_ready() real (npu feature + staged runtime) (P2) 2026-07-05 19:40:27 -05:00
iamdoubz 9ae02cabfe docs(transcription): update OnnxTranscriber name in doc comments (P2) 2026-07-05 19:40:17 -05:00
iamdoubz eb87bf4edb refactor(transcription): re-export OnnxTranscriber; note ONNX tier covers NPU+DirectML (P2) 2026-07-05 19:40:17 -05:00
iamdoubz 0f93f5947e feat(transcription): generalize OnnxNpuTranscriber -> OnnxTranscriber with DirectML EP (P2)
load() now selects OpenVINO (NPU) or DirectML (AMD/Intel GPU) by BackendId over
the same ONNX artifacts; ensure_runtime_env takes the target runtime DLL. Adds
an opt-in directml_transcribes_speech spike for on-GPU validation.
2026-07-05 19:40:16 -05:00