Commit Graph
434 Commits
Author SHA1 Message Date
iamdoubz b5f5ef172c feat(commands): auto-label the mic speaker "You" at stop_recording
Wires VoiceSample creation into start_recording (mic-enabled path) and
runs the voiceprint match after the final diarization pass in
stop_recording: on a confident match, persists "You" and "Speaker 2",
"Speaker 3"... via the existing rename_speaker store path, skipping any
label the user already renamed live.
2026-07-10 19:05:28 -05:00
iamdoubz 69eedc9354 feat(core): track the mic voiceprint sample on RecordingSession
mic_voice_sample carries the VoiceSample handle from start_recording
through to stop_recording so the final diarization pass can run the
mic-speaker voiceprint match.
2026-07-10 19:05:23 -05:00
iamdoubz c9b5b91473 chore(diarization): register the new voiceprint module 2026-07-10 19:05:18 -05:00
iamdoubz dca797aaa3 feat(diarization): voiceprint match to identify the mic speaker cluster
Mic and system audio are already summed into one mono stream before
diarization runs, so clustering alone can't tell which cluster is the
user's own voice. match_mic_speaker compares a mic-only sample's speaker
embedding (same sherpa-onnx model diarization already uses) against each
diarized cluster's own audio and returns a label->name map: best match ->
"You", the rest -> "Speaker 2", "Speaker 3", etc. Returns empty (no
guessing) when the mic sample is too short or no cluster clears the
similarity threshold.
2026-07-10 19:05:14 -05:00
iamdoubz b532acbb3c feat(audio): capture a bounded mic-only sample for voiceprint matching
VoiceSample collects the first ~8s of raw 16kHz-mono mic audio during a
recording, then stops accepting once full. Feeds the mic-speaker
voiceprint match in diarization::voiceprint (bug: mic speaker mislabeled
S1/S2 instead of "You").
2026-07-10 19:05:07 -05:00
iamdoubz 469df7524f fix(transcription): drop whisper-hallucinated segments on silent windows 2026-07-10 18:51:08 -05:00
iamdoubz ec864c24f0 fix(transcription): medium quantized model only exists as q5_0 upstream 2026-07-10 18:51:07 -05:00
iamdoubz 9f1fc671da Merge pull request 'Feature chore bug 005' (#19) from feature_chore_bug_005 into main
Reviewed-on: #19
v0.3.0
2026-07-07 22:02:41 -05:00
iamdoubz 3372dd7490 Bump new release version 0.3.0 2026-07-07 21:54:21 -05:00
iamdoubz a32acba157 chore: bump version to 0.3.0 2026-07-07 21:33:22 -05:00
iamdoubz d9f4fd0960 chore: bump version to 0.3.0 2026-07-07 21:33:21 -05:00
iamdoubz ff74e91f69 chore: bump version to 0.3.0 2026-07-07 21:33:19 -05:00
iamdoubz e557d7599f chore: bump version to 0.3.0 2026-07-07 21:33:18 -05:00
iamdoubz 678f8bee0f Add memanto memories 2026-07-07 21:29:57 -05:00
iamdoubz 1cf0be1259 test(commands): cover graph_calendar_enabled in the privacy egress allowlist test (M4.4) 2026-07-07 18:00:20 -05:00
iamdoubz b14cba2a49 docs(roadmap): mark M4 items shipped, M4.4 MS Graph calendar source complete 2026-07-07 17:58:34 -05:00
iamdoubz 7df76dff00 docs: MS Graph calendar commands/events + fix stale CalendarSource trait signature (T8.9, M4.4) 2026-07-07 17:58:09 -05:00
iamdoubz a48550da1e style(sync): cargo fmt 2026-07-07 17:57:13 -05:00
iamdoubz ce4c54c93b style(commands): cargo fmt 2026-07-07 17:57:12 -05:00
iamdoubz aa5ae127b3 style(calendar): cargo fmt 2026-07-07 17:57:10 -05:00
iamdoubz 3d90265e8f chore(lib): register MS Graph calendar commands (T8.9, M4.4) 2026-07-07 17:53:31 -05:00
iamdoubz d81b4726f9 feat(commands): MS Graph calendar link/import/disconnect + egress allowlist (T8.9, M4.4, FR-CAL-6) 2026-07-07 17:53:13 -05:00
iamdoubz ef6bb28f3e feat(models): add graph_calendar Settings fields (T8.9, M4.4) 2026-07-07 17:51:48 -05:00
iamdoubz d407be8bb0 feat(calendar): GraphSource for MS Graph calendar import (T8.9, M4.4, FR-CAL-6) 2026-07-07 17:51:40 -05:00
iamdoubz 8a80580851 chore(sync): expose resolve_access_token to crate for calendar reuse (M4.4) 2026-07-07 17:49:32 -05:00
iamdoubz 83cb30ef0e feat(calendar): add graph-calendar OAuth provider (T8.9, M4.4) 2026-07-07 17:49:25 -05:00
iamdoubz 6991c1d1bc feat(sync): Dropbox and Box upload targets (T9.10, M4.3)
DropboxTarget: path-addressed like OneDrive/WebDAV; create_folder_v2 creates
the whole intermediate path in one call; upload-session chunking above
LARGE_FILE_THRESHOLD (start/append_v2/finish).

BoxTarget: Box addresses items by numeric ID, not path, so ensure_dir/exists/
put all walk (and lazily create) the folder chain from root ("0") by listing
each level's children. Always uploads via Box's session API regardless of
file size rather than its simple multipart endpoint, since the session API
takes plain PUT bodies (consistent with every other target here) and needs
no new reqwest feature; Box computes and returns each part's digest, so no
local hashing is needed either.

Both follow the same documented ceiling as OneDriveTarget's put_chunked
(M4.1): the upload-session id lives only for one put() call, not persisted
across a durable-queue retry after a restart.

Tests: in-process std::net mock servers for both providers (same pattern as
the existing MockNextcloud/MockGraph), each exercising a real multi-chunk
upload end-to-end.
2026-07-07 14:46:43 -05:00
iamdoubz 40709b257d fix(transcription): resolve_language normalizes case-insensitive "en" match (T8.7, M4.2)
resolve_language(Some("EN"), false) was passed through unchanged instead of
being normalized to lowercase "en" - the English-only-model guard only fired
when the requested language *differed* from English, not when it matched with
different casing. Also fixes cargo fmt drift in mod.rs/npu.rs left over from
the M4.2 worktree (stopped mid-verification per session instruction before
running fmt).
2026-07-07 13:59:55 -05:00
iamdoubz 4e33e7d84c Merge branch 'm4-2-work' into feature_chore_bug_005 2026-07-07 13:33:14 -05:00
iamdoubz e7cc433aff fix(ui): compute activeModel via $derived instead of invalid {@const} placement (T8.7) 2026-07-07 13:32:26 -05:00
iamdoubz 2cc48c9d4d feat(sync): chunked/resumable upload for large recordings (T9.2, M4.1)
Recordings are now native-quality (~50-100 MB) and put() used to buffer
the whole file into memory with a single PUT/upload call; OneDrive/Graph
also caps a single PUT at 250 MB. This replaces that with disk-streamed,
chunked uploads on both sync backends (FR-SYNC-2/5):

- Both WebDavTarget::put and OneDriveTarget::put now stream the file off
  disk in fixed-size buffers (tokio::fs::File + BufReader) instead of
  tokio::fs::read()'ing it whole — memory use is O(chunk), not O(file
  size), for every upload, large or small.
- Files at or below LARGE_FILE_THRESHOLD (8 MiB) still take a single
  streamed PUT; only large artifacts (in practice, .wav recordings) take
  the chunked path, so small transcript/notes/summary uploads are
  unaffected.
- WebDAV (Nextcloud/ownCloud): implements the chunking-v2 protocol —
  MKCOL an upload collection keyed deterministically off the remote
  path's sha256 (stable across retries), PUT lexically-sortable parts,
  MOVE the virtual `.file` to assemble server-side. A retry PROPFINDs
  the collection first and skips any part already landed, so a
  partially-uploaded large file resumes instead of restarting at byte 0
  — genuine mid-file resume, not just chunk-level retry. Generic WebDAV
  targets (Seafile, Synology, unbranded servers) have no equivalent
  server-side assembly endpoint, so they fall back to one streamed PUT
  above the threshold too — memory-safe, just not chunk-resumable
  (documented ponytail simplification).
- OneDrive/Graph: implements the createUploadSession + Content-Range
  byte-range PUT flow (chunks capped at 10 MiB, a multiple of Graph's
  required 320 KiB granularity). A failed chunk is retried a few times
  within the same put() call. ponytail-documented ceiling: the session
  URL isn't persisted on the sync_jobs row, so a retry from a *later*
  pump cycle (e.g. after an app restart) starts a fresh session and
  re-uploads from byte 0 rather than resuming — true cross-attempt
  resume would need a sync_jobs column, left as a follow-up.
- Progress is reported via the existing ProgressSink after each chunk,
  not just once at the end, so the UI sees steady movement on a large
  upload (FR-SYNC-11).
- OneDriveTarget's Graph URLs are now built from a `graph_base()` helper
  (overridable via WA_GRAPH_BASE_URL, unset in production) so the
  chunked session flow can be exercised against a local mock in tests.

Tests (all against small, in-process, dependency-free mock servers —
std::net only, no new crates, same pattern as oauth::LoopbackRedirect):
- nextcloud_chunked_upload_assembles_and_resumes: multi-chunk upload
  assembles byte-for-byte, then a resumed upload with one chunk
  pre-seeded skips exactly that chunk.
- small_file_skips_chunking_even_on_a_chunking_capable_target: a small
  file never takes the chunked path.
- onedrive_chunked_upload_via_graph_session_mock: multi-chunk Graph
  upload session assembles byte-for-byte with per-chunk progress.
- parse_chunk_sizes_extracts_href_and_length_ignoring_namespace_prefix
  and chunk_name_is_zero_padded_and_lexically_sortable: pure unit tests
  for the PROPFIND-response scraper and chunk-naming scheme.

Skip-if-unchanged (SHA-256, in storage::upsert_sync_job) and the
exponential-backoff retry queue (storage::claim_due_sync_jobs) are
untouched — this only changes how SyncTarget::put moves bytes.

Verified: cargo fmt clean; cargo clippy --features sync and --features
mcp both clean (-D warnings); cargo test --lib (default features:
audio, cpu-transcription, diarization, pst, sync, npu) 165 passed, 0
failed, 7 ignored (unrelated hardware-gated tests); cargo test --features
sync --lib: 18 passed, 0 failed, 1 ignored (webdav_round_trip, opt-in
live-server test per existing convention).
2026-07-07 13:32:09 -05:00
iamdoubz be025bbd6c chore(sync): enable tokio io-util/net for disk-streamed chunked upload (M4.1)
Needed for AsyncReadExt/AsyncSeekExt/BufReader used to stream .wav
recordings off disk in fixed-size chunks instead of buffering the
whole file in memory (T9.2 refinement, FR-SYNC-5).
2026-07-07 13:31:49 -05:00
iamdoubz 7ebd34ae08 fix(test): add missing language field to NewMeeting in smoke test (T8.7) 2026-07-07 13:14:38 -05:00
iamdoubz 353d582e96 feat(ui): show meeting language badge + reprocess language picker (T8.7, M4.2) 2026-07-07 13:12:51 -05:00
iamdoubz 7bff39271c feat(ui): thread optional language override through meetings.reprocess (T8.7, M4.2) 2026-07-07 13:12:46 -05:00
iamdoubz e6e995efe0 feat(ui): Transcription Language picker in Settings > Hardware (T8.7, M4.2) 2026-07-07 13:11:36 -05:00
iamdoubz 2cdae9b20d docs(api): document whisper language selection contract surface (T8.7, M4.2) 2026-07-07 13:10:06 -05:00
iamdoubz dc969df792 feat(ui): pass configured whisper_language when starting a recording (T8.7, M4.2) 2026-07-07 13:09:21 -05:00
iamdoubz 489271964f feat(ui): load language catalog + setWhisperLanguage in settings store (T8.7, M4.2) 2026-07-07 13:08:59 -05:00
iamdoubz 4c00496c09 feat(ui): typed API surface for whisper language selection (T8.7, M4.2) 2026-07-07 13:08:13 -05:00
iamdoubz 7490ff5db4 feat(transcription): wire language selection through recording/reprocess/recovery (T8.7, M4.2) 2026-07-07 13:06:00 -05:00
iamdoubz 34fff3f7de feat(core): register list_whisper_languages Tauri command (T8.7, M4.2) 2026-07-07 13:05:55 -05:00
iamdoubz 7675e0467e fix(diarization): set multilingual:false for the shared ModelInfo shape (T8.7) 2026-07-07 13:05:36 -05:00
iamdoubz 75ca3df0a0 feat(core): track resolved per-meeting language on RecordingSession (T8.7, M4.2) 2026-07-07 13:02:24 -05:00
iamdoubz 66d9eff2f9 feat(storage): persist requested language at meeting creation (T8.7, M4.2) 2026-07-07 13:02:14 -05:00
iamdoubz 1fb1da0946 feat(transcription): thread language param through OnnxTranscriber (ignored on NPU/DirectML, T8.7) 2026-07-07 13:01:17 -05:00
iamdoubz 496a8aa29b feat(transcription): wire whisper language param through Transcriber trait (T8.7, M4.2) 2026-07-07 13:00:52 -05:00
iamdoubz 7f88101a79 feat(transcription): whisper language catalog for Settings dropdown (T8.7, M4.2) 2026-07-07 13:00:48 -05:00
iamdoubz 37a6dd172d feat(transcription): multilingual model catalog entries (T8.7, M4.2) 2026-07-07 12:58:52 -05:00
iamdoubz 6bc0949e7e feat(transcription): add multilingual/language fields to ModelInfo+Settings (T8.7, M4.2) 2026-07-07 12:58:12 -05:00