Compare commits

...

8 Commits

Author SHA1 Message Date
leo 5477de17f4 (transcription) fix broken speaker assignment tests
Fix broken speaker assignement tests following #1522.
2026-07-21 19:00:58 +02:00
snyk-bot e8d6aba306 ⬆️(frontend) upgrade @tanstack/react-query from 5.101.0 to 5.101.1
Snyk has created this PR to upgrade @tanstack/react-query from 5.101.0 to 5.101.1.

See this package in npm:
@tanstack/react-query

See this project in Snyk:
https://app.eu.snyk.io/org/lasuite-dinum-default/project/96ea03d8-8d09-493d-86bf-363f274e129e?utm_source=github&utm_medium=referral&page=upgrade-pr
2026-07-21 18:41:15 +02:00
snyk-bot 449503208a ⬆️(frontend) upgrade posthog-js from 1.391.2 to 1.395.0
Snyk has created this PR to upgrade posthog-js from 1.391.2 to 1.395.0.

See this package in npm:
posthog-js

See this project in Snyk:
https://app.eu.snyk.io/org/lasuite-dinum-default/project/96ea03d8-8d09-493d-86bf-363f274e129e?utm_source=github&utm_medium=referral&page=upgrade-pr
2026-07-21 18:34:52 +02:00
snyk-bot 7eb3553bea ⬆️(frontend) upgrade i18next from 26.3.1 to 26.3.2
Snyk has created this PR to upgrade i18next from 26.3.1 to 26.3.2.

See this package in npm:
i18next

See this project in Snyk:
https://app.eu.snyk.io/org/lasuite-dinum-default/project/af693e79-8c43-4c09-ab65-60580515c9e8?utm_source=github&utm_medium=referral&page=upgrade-pr
2026-07-21 18:24:25 +02:00
snyk-bot f0356af365 ⬆️(frontend) upgrade @mediapipe/tasks-vision from 0.10.14 to 0.10.35
Snyk has created this PR to upgrade @mediapipe/tasks-vision from 0.10.14 to 0.10.35.

See this package in npm:
@mediapipe/tasks-vision

See this project in Snyk:
https://app.eu.snyk.io/org/lasuite-dinum-default/project/96ea03d8-8d09-493d-86bf-363f274e129e?utm_source=github&utm_medium=referral&page=upgrade-pr
2026-07-21 18:19:26 +02:00
leo 9921ef9d09 🐛(transcription) fix silent fail of speaker assignment
Fix bug introduced by #1362 which caused speaker assignment to
silently fail. Bug was due to change in input variable type.
2026-07-21 18:16:23 +02:00
lebaudantoine 68e999a037 🔖(minor) bump release to 1.24.0 2026-07-21 18:01:20 +02:00
lebaudantoine 34103bf326 🩹(agents) announce the update of uv.lock via prepare-release script
Announce it among the other files. Minor issue.
2026-07-21 18:01:20 +02:00
17 changed files with 79 additions and 62 deletions
+13
View File
@@ -8,6 +8,19 @@ and this project adheres to
## [Unreleased]
## Fixed
- 🐛(transcription) fix silent bug in speaker assignment
### Changed
- ⬆️(frontend) upgrade @mediapipe/tasks-vision from 0.10.14 to 0.10.35
- ⬆️(frontend) upgrade i18next from 26.3.1 to 26.3.2
- ⬆️(frontend) upgrade posthog-js from 1.391.2 to 1.395.0
- ⬆️(frontend) upgrade @tanstack/react-query from 5.101.0 to 5.101.1
## [1.24.0] - 2026-07-21
### Added
- ✨(backend) allow searching the recording admin table by owner email
+1
View File
@@ -164,6 +164,7 @@ echo " - src/backend/pyproject.toml"
echo " - src/backend/uv.lock"
echo " - src/summary/pyproject.toml"
echo " - src/agents/pyproject.toml"
echo " - src/agents/uv.lock"
echo " - CHANGELOG.md"
echo ""
print_warning "Next steps:"
+4 -4
View File
@@ -10,7 +10,7 @@
"license": "MIT",
"dependencies": {
"core-js": "3.49.0",
"i18next": "26.3.1",
"i18next": "^26.3.2",
"i18next-browser-languagedetector": "8.2.1",
"regenerator-runtime": "0.14.1"
},
@@ -9364,9 +9364,9 @@
}
},
"node_modules/i18next": {
"version": "26.3.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.1.tgz",
"integrity": "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ==",
"version": "26.3.2",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.2.tgz",
"integrity": "sha512-QQkXAM1sPDHqhxMQuBeHVMUn6mJchF+wdpOoQerciLAFqO3ZYdxO0EUbeEhruyutnNwpUQIITDVzLjwnNL0T1w==",
"funding": [
{
"type": "individual",
+1 -1
View File
@@ -27,7 +27,7 @@
},
"dependencies": {
"core-js": "3.49.0",
"i18next": "26.3.1",
"i18next": "26.3.2",
"i18next-browser-languagedetector": "8.2.1",
"regenerator-runtime": "0.14.1"
},
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "agents"
version = "1.23.0"
version = "1.24.0"
requires-python = ">=3.12"
dependencies = [
"livekit-agents==1.6.4",
+1 -1
View File
@@ -9,7 +9,7 @@ resolution-markers = [
[[package]]
name = "agents"
version = "1.23.0"
version = "1.24.0"
source = { virtual = "." }
dependencies = [
{ name = "livekit-agents" },
+1 -1
View File
@@ -7,7 +7,7 @@ build-backend = "uv_build"
[project]
name = "meet"
version = "1.23.0"
version = "1.24.0"
authors = [{ "name" = "DINUM", "email" = "dev@mail.numerique.gouv.fr" }]
classifiers = [
"Development Status :: 5 - Production/Stable",
+1 -1
View File
@@ -1187,7 +1187,7 @@ wheels = [
[[package]]
name = "meet"
version = "1.23.0"
version = "1.24.0"
source = { editable = "." }
dependencies = [
{ name = "aiohttp" },
+24 -18
View File
@@ -1,12 +1,12 @@
{
"name": "meet",
"version": "1.23.0",
"version": "1.24.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "meet",
"version": "1.23.0",
"version": "1.24.0",
"dependencies": {
"@fontsource-variable/atkinson-hyperlegible-next": "5.2.6",
"@fontsource-variable/lexend": "5.2.11",
@@ -15,11 +15,11 @@
"@livekit/components-react": "2.9.21",
"@livekit/components-styles": "1.2.0",
"@livekit/track-processors": "0.7.2",
"@mediapipe/tasks-vision": "0.10.14",
"@mediapipe/tasks-vision": "0.10.35",
"@pandacss/preset-panda": "1.11.3",
"@react-types/overlays": "3.10.0",
"@remixicon/react": "4.9.0",
"@tanstack/react-query": "5.101.0",
"@tanstack/react-query": "5.101.1",
"@timephy/rnnoise-wasm": "1.0.0",
"crisp-sdk-web": "1.1.2",
"derive-valtio": "0.2.0",
@@ -30,7 +30,7 @@
"i18next-parser": "9.4.0",
"i18next-resources-to-backend": "1.2.1",
"livekit-client": "2.19.2",
"posthog-js": "1.391.2",
"posthog-js": "1.395.0",
"react": "18.3.1",
"react-aria": "3.50.0",
"react-aria-components": "1.19.0",
@@ -1049,12 +1049,18 @@
"livekit-client": "^1.12.0 || ^2.1.0"
}
},
"node_modules/@mediapipe/tasks-vision": {
"node_modules/@livekit/track-processors/node_modules/@mediapipe/tasks-vision": {
"version": "0.10.14",
"resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.14.tgz",
"integrity": "sha512-vOifgZhkndgybdvoRITzRkIueWWSiCKuEUXXK6Q4FaJsFvRJuwgg++vqFUMlL0Uox62U5aEXFhHxlhV7Ja5e3Q==",
"license": "Apache-2.0"
},
"node_modules/@mediapipe/tasks-vision": {
"version": "0.10.35",
"resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.35.tgz",
"integrity": "sha512-HOvadwVRE6JC+45nyYhmnywnr5h/J8KZvOeUNVOG9q/0875pZgItznFB9bRTvLc264YSJqiZ1NsIpCStJw/egg==",
"license": "Apache-2.0"
},
"node_modules/@modelcontextprotocol/sdk": {
"version": "1.29.0",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz",
@@ -2415,9 +2421,9 @@
}
},
"node_modules/@tanstack/query-core": {
"version": "5.101.0",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.0.tgz",
"integrity": "sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==",
"version": "5.101.1",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.1.tgz",
"integrity": "sha512-Y6Y92dkXtNqx67m2pMSxUsA3zOCwv862JexZRP8/EPwvKXMPu9m8rv43spiXWzOUIggQ3SQApttALStzhA8B4g==",
"license": "MIT",
"funding": {
"type": "github",
@@ -2436,12 +2442,12 @@
}
},
"node_modules/@tanstack/react-query": {
"version": "5.101.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.0.tgz",
"integrity": "sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==",
"version": "5.101.1",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.1.tgz",
"integrity": "sha512-ZnONUuQKJe1bJMStXUL1s5uKN9FcfC28j5cK+iDZcdSHtUv1wtin1cGc/Oewhf2Oc4eKY7lggtpvT/AbMmhHew==",
"license": "MIT",
"dependencies": {
"@tanstack/query-core": "5.101.0"
"@tanstack/query-core": "5.101.1"
},
"funding": {
"type": "github",
@@ -9130,13 +9136,13 @@
"license": "MIT"
},
"node_modules/posthog-js": {
"version": "1.391.2",
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.391.2.tgz",
"integrity": "sha512-q0DZN6ljchSnAFJIXf+sQFTPlsLjTlRa+TvrL+QRb6413BGtib/MNiQy1bnwLKt8KR+f6xJYvkqdLyty9s4Aww==",
"version": "1.395.0",
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.395.0.tgz",
"integrity": "sha512-5iTb00CGt2eQUUiBQysQiX89RAbCN6wK2sDNzvs9zv0alaY8mJ0ZySrUD3LQ+XyLhgM5pCpacBuUwChqiYDLDw==",
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
"@posthog/core": "^1.35.3",
"@posthog/types": "^1.390.2",
"@posthog/core": "^1.38.0",
"@posthog/types": "^1.391.1",
"core-js": "^3.38.1",
"dompurify": "^3.3.2",
"fflate": "^0.4.8",
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "meet",
"private": true,
"version": "1.23.0",
"version": "1.24.0",
"type": "module",
"scripts": {
"dev": "panda codegen && vite",
@@ -22,11 +22,11 @@
"@livekit/components-react": "2.9.21",
"@livekit/components-styles": "1.2.0",
"@livekit/track-processors": "0.7.2",
"@mediapipe/tasks-vision": "0.10.14",
"@mediapipe/tasks-vision": "0.10.35",
"@pandacss/preset-panda": "1.11.3",
"@react-types/overlays": "3.10.0",
"@remixicon/react": "4.9.0",
"@tanstack/react-query": "5.101.0",
"@tanstack/react-query": "5.101.1",
"@timephy/rnnoise-wasm": "1.0.0",
"crisp-sdk-web": "1.1.2",
"derive-valtio": "0.2.0",
@@ -37,7 +37,7 @@
"i18next-parser": "9.4.0",
"i18next-resources-to-backend": "1.2.1",
"livekit-client": "2.19.2",
"posthog-js": "1.391.2",
"posthog-js": "1.395.0",
"react": "18.3.1",
"react-aria": "3.50.0",
"react-aria-components": "1.19.0",
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "mail_mjml",
"version": "1.23.0",
"version": "1.24.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mail_mjml",
"version": "1.23.0",
"version": "1.24.0",
"license": "MIT",
"dependencies": {
"@html-to/text-cli": "0.6.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "mail_mjml",
"version": "1.23.0",
"version": "1.24.0",
"description": "An util to generate html and text django's templates from mjml templates",
"type": "module",
"dependencies": {
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "sdk",
"version": "1.23.0",
"version": "1.24.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sdk",
"version": "1.23.0",
"version": "1.24.0",
"license": "ISC",
"workspaces": [
"./library",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "sdk",
"version": "1.23.0",
"version": "1.24.0",
"author": "",
"license": "ISC",
"description": "",
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "summary"
version = "1.23.0"
version = "1.24.0"
dependencies = [
"fastapi[standard]>=0.105.0",
"uvicorn>=0.24.0",
+1 -1
View File
@@ -275,7 +275,7 @@ def _build_participant_timelines(
def _build_speaker_timelines(transcription: Any) -> dict[str, list[Interval]]:
"""Build interval timelines from WhisperX transcription segments."""
intervals: dict[str, list[Interval]] = {}
segments = transcription.segments if hasattr(transcription, "segments") else []
segments = transcription.get("segments") or []
max_word_duration = settings.resolve_speaker_identities_max_word_duration
for segment in segments:
+20 -23
View File
@@ -1,7 +1,6 @@
"""Tests for the speaker-to-user assignment service."""
import math
from dataclasses import dataclass, field
from datetime import datetime
from summary.core import user_assign
@@ -17,11 +16,9 @@ from summary.core.user_assign import (
)
@dataclass
class FakeTranscription:
"""Mimics the OpenAI Transcription pydantic model for testing."""
segments: list = field(default_factory=list)
def make_transcription(segments: list | None = None) -> dict:
"""Build a WhisperX transcription dict, matching WhisperXResponse.model_dump()."""
return {"segments": segments or []}
RECORDING_START = datetime.fromisoformat("2026-03-17T15:30:33.000001")
@@ -68,7 +65,7 @@ METADATA_SINGLE_USER = {
],
}
DIARIZATION_SINGLE_SPEAKER = FakeTranscription(
DIARIZATION_SINGLE_SPEAKER = make_transcription(
segments=[
{
"start": 1.363,
@@ -182,7 +179,7 @@ class TestBuildSpeakerTimelines:
def test_segment_without_words_falls_back_to_segment_bounds(self):
"""Segments missing a `words` key use the segment start/end as one interval."""
transcription = FakeTranscription(
transcription = make_transcription(
segments=[{"start": 1.5, "end": 3.5, "speaker": "SPEAKER_00"}],
)
result = _build_speaker_timelines(transcription)
@@ -190,7 +187,7 @@ class TestBuildSpeakerTimelines:
def test_segment_with_only_none_word_timestamps_falls_back(self):
"""If every word has None start/end, fall back to segment bounds."""
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{
"start": 1.0,
@@ -208,7 +205,7 @@ class TestBuildSpeakerTimelines:
def test_short_words_only_uses_segment_start_and_last_word_end(self):
"""With no overly long words, the interval runs segment start to end."""
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{
"start": 1.0,
@@ -231,7 +228,7 @@ class TestBuildSpeakerTimelines:
max_word_duration = (
user_assign.settings.resolve_speaker_identities_max_word_duration
)
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{
"start": 0.0,
@@ -252,7 +249,7 @@ class TestBuildSpeakerTimelines:
def test_long_word_in_middle_splits_segment(self):
"""Short words around a long word produce two intervals (before-cap + after)."""
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{
"start": 0.0,
@@ -275,7 +272,7 @@ class TestBuildSpeakerTimelines:
def test_tail_word_is_capped_at_max_duration(self):
"""The trailing word's end is capped at word.start + max_word_duration."""
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{
"start": 0.0,
@@ -302,7 +299,7 @@ class TestBuildSpeakerTimelines:
update={"resolve_speaker_identities_enable_split_on_words": False},
),
)
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{
"start": 0.0,
@@ -322,7 +319,7 @@ class TestBuildSpeakerTimelines:
def test_multiple_speakers_keep_separate_timelines(self):
"""Segments from different speakers populate independent timeline entries."""
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{
"start": 0.0,
@@ -402,7 +399,7 @@ class TestResolveSpeakerIdentities:
],
"participants": [{"participantId": "user-a", "name": "Shared Mic"}],
}
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{"start": 1.0, "end": 3.0, "speaker": "SPEAKER_00"},
{"start": 5.0, "end": 7.0, "speaker": "SPEAKER_01"},
@@ -445,7 +442,7 @@ class TestResolveSpeakerIdentities:
{"participantId": "user-b", "name": "Bob"},
],
}
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{"start": 1.5, "end": 3.5, "speaker": "SPEAKER_00"},
{"start": 5.5, "end": 7.5, "speaker": "SPEAKER_01"},
@@ -493,7 +490,7 @@ class TestResolveSpeakerIdentities:
{"participantId": "user-b", "name": "Bob"},
],
}
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{"start": 1.5, "end": 5.5, "speaker": "SPEAKER_00"},
{"start": 4.0, "end": 7.5, "speaker": "SPEAKER_01"},
@@ -529,7 +526,7 @@ class TestResolveSpeakerIdentities:
],
"participants": [{"participantId": "user-a", "name": "Brief User"}],
}
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{"start": 1.0, "end": 10.0, "speaker": "SPEAKER_00"},
],
@@ -561,7 +558,7 @@ class TestResolveSpeakerIdentities:
],
"participants": [{"participantId": "user-a", "name": "Early User"}],
}
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{"start": 0.0, "end": 3.0, "speaker": "SPEAKER_00"},
],
@@ -576,7 +573,7 @@ class TestResolveSpeakerIdentities:
"""No segments produces empty result."""
result = resolve_speaker_identities(
METADATA_SINGLE_USER,
FakeTranscription(segments=[]),
make_transcription(segments=[]),
RECORDING_START,
RECORDING_END,
)
@@ -584,7 +581,7 @@ class TestResolveSpeakerIdentities:
def test_segment_without_speaker_ignored(self):
"""Segments missing speaker key are skipped."""
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{"start": 1.0, "end": 3.0, "text": "no speaker"},
],
@@ -608,7 +605,7 @@ class TestResolveSpeakerIdentities:
],
"participants": [{"participantId": "user-a", "name": "Still Talking"}],
}
transcription = FakeTranscription(
transcription = make_transcription(
segments=[
{"start": 2.0, "end": 9.0, "speaker": "SPEAKER_00"},
],