Skip to content

Release packages - #1423

Open
knope-bot[bot] wants to merge 1 commit into
mainfrom
knope/release
Open

knope-bot[bot] wants to merge 1 commit into
mainfrom
knope/release

Conversation

@knope-bot

@knope-bot knope-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Important

Merging this pull request will create these releases

livekit-datatrack 0.1.16 (2026-09-22)

Features

EncryptionError::Failed and DecryptionError::Failed carry a reason string and are no longer flat_error,

so a foreign EncryptionProvider or DecryptionProvider returning an error no longer aborts the process with
"Can't lift flat errors" -- a failed data track decrypt (no E2EE manager, key mismatch, corrupt frame) now
drops the frame and leaves the room connected.

libwebrtc 0.3.49 (2026-09-22)

Fixes

  • Correct the AppKit framework name so macOS linking works with case-sensitive SDK filesystems.

livekit 0.9.2 (2026-09-22)

Fixes

  • Correct the AppKit framework name so macOS linking works with case-sensitive SDK filesystems.
  • Fix reliable data channel replay: keep the full retry buffer across resumes, drop duplicate reliable packets, and ignore replayed chunks on uncompressed streams instead of failing with MissedChunk.
  • Stop answering a server-initiated Leave (room deleted, duplicate identity) with a client Leave. The server has already ended the session and is closing the signalling socket, so the reply only ever produced the warning "dropping pass-through signal — no stream available" on every such disconnect.

Fix the RTC engine leaking when a room is dropped without being closed.

The engine's event task held a strong reference to the engine, while the signal that stops
that task lives inside the engine itself, so the two kept each other alive. An engine
dropped without an explicit close() released nothing: the session, both peer connections,
the WebRTC runtime, and the signal client with its open websocket all stayed resident for
the lifetime of the process, and the server kept its half of the session because the socket
was never closed. The task now holds a weak reference and stops on its own once the engine
is gone.

EncryptionError::Failed and DecryptionError::Failed carry a reason string and are no longer flat_error,

so a foreign EncryptionProvider or DecryptionProvider returning an error no longer aborts the process with
"Can't lift flat errors" -- a failed data track decrypt (no E2EE manager, key mismatch, corrupt frame) now
drops the frame and leaves the room connected.

Report the reconnect reason to the server when resuming.

Resumes previously sent no reason, so server-side telemetry could not attribute why Rust
clients reconnect — every resume looked like RR_UNKNOWN. The engine now records what caused
the episode (signal disconnected, publisher failed, subscriber failed) and reports it on each
resume attempt. The v0 signalling path was also missing the reconnect_reason query parameter
entirely, so it would not have been reported even if a reason had been supplied.

Fix resume reporting success for a PeerConnection that had not recovered.

A resume decided recovery from PeerConnectionState, which keeps reading Connected for tens
of seconds after the far end goes away. A resume could therefore emit Resumed — and so
RoomEvent::Reconnected with ConnectionState::Connected — for a session whose subscriber
transport was dead, leaving applications with no signal that they had stopped receiving media.
A resume now requires each transport to have entered Connected since the resume began, or to
have held it throughout, rather than trusting the state it currently reports.

VideoGrants gains the agent grant and Claims the kind claim (with

AccessToken::with_kind), which the Go, Python and JS SDKs already carry. An
agent worker's token is VideoGrants { agent: true } and a simulated job's
participant token is kind: "agent"; neither could be minted from Rust before.
livekit-uniffi exposes both: TokenOptions.kind, Claims.kind, and agent
on its VideoGrants record.

Breaking: the four grants the server infers when absent -- can_publish,
can_subscribe, can_publish_data, can_update_own_metadata -- are now
Option<bool>, as in the Go and JS SDKs. None leaves the decision to the
server, and the new getters (can_publish(), can_subscribe(),
can_publish_data(), can_update_own_metadata()) read a token the way the
server does, can_publish_data falling back to can_publish included. Code
that set these fields writes Some(..); code that read them uses the getters.
The same fields are optional on the livekit-uniffi record, and
livekit-api re-exports the crate as livekit_api::access_token, so both
carry the change.

Nothing at its default is written into the token any more: unset claims and
grants are omitted, as the server's own omitempty grants are. Verification
of existing tokens is unchanged.

Write the x-google-start-bitrate hint once per publisher connection, and exempt screen share from the 1 Mbps cap.

libwebrtc reads this fmtp parameter per m-section but applies it to the shared Call (WebRtcVideoSendChannel::ApplyChangedParams -> SetSdpBitrateParameters), where RtpBitrateConfigurator holds one config for the whole peer connection. It retains start_bitrate_bps and re-applies it on network route changes (RtpTransportControllerSend::OnNetworkRouteChanged), so a WiFi-to-cellular handover re-seeds the estimator from the original hint with no renegotiation. Rewriting the value on later offers was therefore at best a no-op and at worst a restart of a converged bandwidth estimator; it is now written only on the first offer that carries local video, and only once that offer is accepted locally. A full reconnect builds a new peer connection and seeds the new estimator again. The initial offer sent with the JoinRequest in single PC mode never carries the hint: it is created before any track is published, so no target bitrate exists yet.

Screen share is no longer capped at 1 Mbps, matching client-sdk-js and client-sdk-android: unlike camera content, a screen share is published at a high bitrate so text stays legible, and a conservative start costs more than a brief overshoot.

livekit-data-stream 0.1.6 (2026-09-22)

Fixes

  • Fix reliable data channel replay: keep the full retry buffer across resumes, drop duplicate reliable packets, and ignore replayed chunks on uncompressed streams instead of failing with MissedChunk.

livekit-ffi 0.12.80 (2026-09-22)

Features

  • Add the scaffolding for exposing video capture over FFI.
  • Add a capture source that renders a wall clock on the GPU.
  • Add a capture source that renders a test pattern on the GPU.

Fixes

  • Correct the AppKit framework name so macOS linking works with case-sensitive SDK filesystems.
  • Fix reliable data channel replay: keep the full retry buffer across resumes, drop duplicate reliable packets, and ignore replayed chunks on uncompressed streams instead of failing with MissedChunk.
  • Stop answering a server-initiated Leave (room deleted, duplicate identity) with a client Leave. The server has already ended the session and is closing the signalling socket, so the reply only ever produced the warning "dropping pass-through signal — no stream available" on every such disconnect.

Fix the RTC engine leaking when a room is dropped without being closed.

The engine's event task held a strong reference to the engine, while the signal that stops
that task lives inside the engine itself, so the two kept each other alive. An engine
dropped without an explicit close() released nothing: the session, both peer connections,
the WebRTC runtime, and the signal client with its open websocket all stayed resident for
the lifetime of the process, and the server kept its half of the session because the socket
was never closed. The task now holds a weak reference and stops on its own once the engine
is gone.

EncryptionError::Failed and DecryptionError::Failed carry a reason string and are no longer flat_error,

so a foreign EncryptionProvider or DecryptionProvider returning an error no longer aborts the process with
"Can't lift flat errors" -- a failed data track decrypt (no E2EE manager, key mismatch, corrupt frame) now
drops the frame and leaves the room connected.

Report the reconnect reason to the server when resuming.

Resumes previously sent no reason, so server-side telemetry could not attribute why Rust
clients reconnect — every resume looked like RR_UNKNOWN. The engine now records what caused
the episode (signal disconnected, publisher failed, subscriber failed) and reports it on each
resume attempt. The v0 signalling path was also missing the reconnect_reason query parameter
entirely, so it would not have been reported even if a reason had been supplied.

Fix resume reporting success for a PeerConnection that had not recovered.

A resume decided recovery from PeerConnectionState, which keeps reading Connected for tens
of seconds after the far end goes away. A resume could therefore emit Resumed — and so
RoomEvent::Reconnected with ConnectionState::Connected — for a session whose subscriber
transport was dead, leaving applications with no signal that they had stopped receiving media.
A resume now requires each transport to have entered Connected since the resume began, or to
have held it throughout, rather than trusting the state it currently reports.

VideoGrants gains the agent grant and Claims the kind claim (with

AccessToken::with_kind), which the Go, Python and JS SDKs already carry. An
agent worker's token is VideoGrants { agent: true } and a simulated job's
participant token is kind: "agent"; neither could be minted from Rust before.
livekit-uniffi exposes both: TokenOptions.kind, Claims.kind, and agent
on its VideoGrants record.

Breaking: the four grants the server infers when absent -- can_publish,
can_subscribe, can_publish_data, can_update_own_metadata -- are now
Option<bool>, as in the Go and JS SDKs. None leaves the decision to the
server, and the new getters (can_publish(), can_subscribe(),
can_publish_data(), can_update_own_metadata()) read a token the way the
server does, can_publish_data falling back to can_publish included. Code
that set these fields writes Some(..); code that read them uses the getters.
The same fields are optional on the livekit-uniffi record, and
livekit-api re-exports the crate as livekit_api::access_token, so both
carry the change.

Nothing at its default is written into the token any more: unset claims and
grants are omitted, as the server's own omitempty grants are. Verification
of existing tokens is unchanged.

Write the x-google-start-bitrate hint once per publisher connection, and exempt screen share from the 1 Mbps cap.

libwebrtc reads this fmtp parameter per m-section but applies it to the shared Call (WebRtcVideoSendChannel::ApplyChangedParams -> SetSdpBitrateParameters), where RtpBitrateConfigurator holds one config for the whole peer connection. It retains start_bitrate_bps and re-applies it on network route changes (RtpTransportControllerSend::OnNetworkRouteChanged), so a WiFi-to-cellular handover re-seeds the estimator from the original hint with no renegotiation. Rewriting the value on later offers was therefore at best a no-op and at worst a restart of a converged bandwidth estimator; it is now written only on the first offer that carries local video, and only once that offer is accepted locally. A full reconnect builds a new peer connection and seeds the new estimator again. The initial offer sent with the JoinRequest in single PC mode never carries the hint: it is created before any track is published, so no target bitrate exists yet.

Screen share is no longer capped at 1 Mbps, matching client-sdk-js and client-sdk-android: unlike camera content, a screen share is published at a high bitrate so text stays legible, and a conservative start costs more than a brief overshoot.

livekit-capture 0.1.2 (2026-09-22)

Features

  • Add a capture source that renders a wall clock on the GPU.
  • Add a capture source that renders a test pattern on the GPU.

Fixes

  • Correct the AppKit framework name so macOS linking works with case-sensitive SDK filesystems.
  • Automatic capture thread join on drop
  • Fix reliable data channel replay: keep the full retry buffer across resumes, drop duplicate reliable packets, and ignore replayed chunks on uncompressed streams instead of failing with MissedChunk.
  • Stop answering a server-initiated Leave (room deleted, duplicate identity) with a client Leave. The server has already ended the session and is closing the signalling socket, so the reply only ever produced the warning "dropping pass-through signal — no stream available" on every such disconnect.

Fix the RTC engine leaking when a room is dropped without being closed.

The engine's event task held a strong reference to the engine, while the signal that stops
that task lives inside the engine itself, so the two kept each other alive. An engine
dropped without an explicit close() released nothing: the session, both peer connections,
the WebRTC runtime, and the signal client with its open websocket all stayed resident for
the lifetime of the process, and the server kept its half of the session because the socket
was never closed. The task now holds a weak reference and stops on its own once the engine
is gone.

EncryptionError::Failed and DecryptionError::Failed carry a reason string and are no longer flat_error,

so a foreign EncryptionProvider or DecryptionProvider returning an error no longer aborts the process with
"Can't lift flat errors" -- a failed data track decrypt (no E2EE manager, key mismatch, corrupt frame) now
drops the frame and leaves the room connected.

Report the reconnect reason to the server when resuming.

Resumes previously sent no reason, so server-side telemetry could not attribute why Rust
clients reconnect — every resume looked like RR_UNKNOWN. The engine now records what caused
the episode (signal disconnected, publisher failed, subscriber failed) and reports it on each
resume attempt. The v0 signalling path was also missing the reconnect_reason query parameter
entirely, so it would not have been reported even if a reason had been supplied.

Fix resume reporting success for a PeerConnection that had not recovered.

A resume decided recovery from PeerConnectionState, which keeps reading Connected for tens
of seconds after the far end goes away. A resume could therefore emit Resumed — and so
RoomEvent::Reconnected with ConnectionState::Connected — for a session whose subscriber
transport was dead, leaving applications with no signal that they had stopped receiving media.
A resume now requires each transport to have entered Connected since the resume began, or to
have held it throughout, rather than trusting the state it currently reports.

Write the x-google-start-bitrate hint once per publisher connection, and exempt screen share from the 1 Mbps cap.

libwebrtc reads this fmtp parameter per m-section but applies it to the shared Call (WebRtcVideoSendChannel::ApplyChangedParams -> SetSdpBitrateParameters), where RtpBitrateConfigurator holds one config for the whole peer connection. It retains start_bitrate_bps and re-applies it on network route changes (RtpTransportControllerSend::OnNetworkRouteChanged), so a WiFi-to-cellular handover re-seeds the estimator from the original hint with no renegotiation. Rewriting the value on later offers was therefore at best a no-op and at worst a restart of a converged bandwidth estimator; it is now written only on the first offer that carries local video, and only once that offer is accepted locally. A full reconnect builds a new peer connection and seeds the new estimator again. The initial offer sent with the JoinRequest in single PC mode never carries the hint: it is created before any track is published, so no target bitrate exists yet.

Screen share is no longer capped at 1 Mbps, matching client-sdk-js and client-sdk-android: unlike camera content, a screen share is published at a high bitrate so text stays legible, and a conservative start costs more than a brief overshoot.

livekit-token 0.2.0 (2026-09-22)

Breaking Changes

VideoGrants gains the agent grant and Claims the kind claim (with

AccessToken::with_kind), which the Go, Python and JS SDKs already carry. An
agent worker's token is VideoGrants { agent: true } and a simulated job's
participant token is kind: "agent"; neither could be minted from Rust before.
livekit-uniffi exposes both: TokenOptions.kind, Claims.kind, and agent
on its VideoGrants record.

Breaking: the four grants the server infers when absent -- can_publish,
can_subscribe, can_publish_data, can_update_own_metadata -- are now
Option<bool>, as in the Go and JS SDKs. None leaves the decision to the
server, and the new getters (can_publish(), can_subscribe(),
can_publish_data(), can_update_own_metadata()) read a token the way the
server does, can_publish_data falling back to can_publish included. Code
that set these fields writes Some(..); code that read them uses the getters.
The same fields are optional on the livekit-uniffi record, and
livekit-api re-exports the crate as livekit_api::access_token, so both
carry the change.

Nothing at its default is written into the token any more: unset claims and
grants are omitted, as the server's own omitempty grants are. Verification
of existing tokens is unchanged.

webrtc-sys 0.3.46 (2026-09-22)

Fixes

  • Correct the AppKit framework name so macOS linking works with case-sensitive SDK filesystems.

livekit-uniffi 0.2.0 (2026-09-22)

Breaking Changes

VideoGrants gains the agent grant and Claims the kind claim (with

AccessToken::with_kind), which the Go, Python and JS SDKs already carry. An
agent worker's token is VideoGrants { agent: true } and a simulated job's
participant token is kind: "agent"; neither could be minted from Rust before.
livekit-uniffi exposes both: TokenOptions.kind, Claims.kind, and agent
on its VideoGrants record.

Breaking: the four grants the server infers when absent -- can_publish,
can_subscribe, can_publish_data, can_update_own_metadata -- are now
Option<bool>, as in the Go and JS SDKs. None leaves the decision to the
server, and the new getters (can_publish(), can_subscribe(),
can_publish_data(), can_update_own_metadata()) read a token the way the
server does, can_publish_data falling back to can_publish included. Code
that set these fields writes Some(..); code that read them uses the getters.
The same fields are optional on the livekit-uniffi record, and
livekit-api re-exports the crate as livekit_api::access_token, so both
carry the change.

Nothing at its default is written into the token any more: unset claims and
grants are omitted, as the server's own omitempty grants are. Verification
of existing tokens is unchanged.

Features

EncryptionError::Failed and DecryptionError::Failed carry a reason string and are no longer flat_error,

so a foreign EncryptionProvider or DecryptionProvider returning an error no longer aborts the process with
"Can't lift flat errors" -- a failed data track decrypt (no E2EE manager, key mismatch, corrupt frame) now
drops the frame and leaves the room connected.

Fixes

  • Fix reliable data channel replay: keep the full retry buffer across resumes, drop duplicate reliable packets, and ignore replayed chunks on uncompressed streams instead of failing with MissedChunk.

Report the reconnect reason to the server when resuming.

Resumes previously sent no reason, so server-side telemetry could not attribute why Rust
clients reconnect — every resume looked like RR_UNKNOWN. The engine now records what caused
the episode (signal disconnected, publisher failed, subscriber failed) and reports it on each
resume attempt. The v0 signalling path was also missing the reconnect_reason query parameter
entirely, so it would not have been reported even if a reason had been supplied.

livekit-api 0.8.0 (2026-09-22)

Breaking Changes

VideoGrants gains the agent grant and Claims the kind claim (with

AccessToken::with_kind), which the Go, Python and JS SDKs already carry. An
agent worker's token is VideoGrants { agent: true } and a simulated job's
participant token is kind: "agent"; neither could be minted from Rust before.
livekit-uniffi exposes both: TokenOptions.kind, Claims.kind, and agent
on its VideoGrants record.

Breaking: the four grants the server infers when absent -- can_publish,
can_subscribe, can_publish_data, can_update_own_metadata -- are now
Option<bool>, as in the Go and JS SDKs. None leaves the decision to the
server, and the new getters (can_publish(), can_subscribe(),
can_publish_data(), can_update_own_metadata()) read a token the way the
server does, can_publish_data falling back to can_publish included. Code
that set these fields writes Some(..); code that read them uses the getters.
The same fields are optional on the livekit-uniffi record, and
livekit-api re-exports the crate as livekit_api::access_token, so both
carry the change.

Nothing at its default is written into the token any more: unset claims and
grants are omitted, as the server's own omitempty grants are. Verification
of existing tokens is unchanged.

Fixes

Report the reconnect reason to the server when resuming.

Resumes previously sent no reason, so server-side telemetry could not attribute why Rust
clients reconnect — every resume looked like RR_UNKNOWN. The engine now records what caused
the episode (signal disconnected, publisher failed, subscriber failed) and reports it on each
resume attempt. The v0 signalling path was also missing the reconnect_reason query parameter
entirely, so it would not have been reported even if a reason had been supplied.

livekit-signaling 0.1.3 (2026-09-22)

Fixes

Report the reconnect reason to the server when resuming.

Resumes previously sent no reason, so server-side telemetry could not attribute why Rust
clients reconnect — every resume looked like RR_UNKNOWN. The engine now records what caused
the episode (signal disconnected, publisher failed, subscriber failed) and reports it on each
resume attempt. The v0 signalling path was also missing the reconnect_reason query parameter
entirely, so it would not have been reported even if a reason had been supplied.

VideoGrants gains the agent grant and Claims the kind claim (with

AccessToken::with_kind), which the Go, Python and JS SDKs already carry. An
agent worker's token is VideoGrants { agent: true } and a simulated job's
participant token is kind: "agent"; neither could be minted from Rust before.
livekit-uniffi exposes both: TokenOptions.kind, Claims.kind, and agent
on its VideoGrants record.

Breaking: the four grants the server infers when absent -- can_publish,
can_subscribe, can_publish_data, can_update_own_metadata -- are now
Option<bool>, as in the Go and JS SDKs. None leaves the decision to the
server, and the new getters (can_publish(), can_subscribe(),
can_publish_data(), can_update_own_metadata()) read a token the way the
server does, can_publish_data falling back to can_publish included. Code
that set these fields writes Some(..); code that read them uses the getters.
The same fields are optional on the livekit-uniffi record, and
livekit-api re-exports the crate as livekit_api::access_token, so both
carry the change.

Nothing at its default is written into the token any more: unset claims and
grants are omitted, as the server's own omitempty grants are. Verification
of existing tokens is unchanged.

livekit-rpc 0.1.2 (2026-09-22)

Fixes

  • Fix reliable data channel replay: keep the full retry buffer across resumes, drop duplicate reliable packets, and ignore replayed chunks on uncompressed streams instead of failing with MissedChunk.

@knope-bot
knope-bot Bot requested review from ladvoc and lukasIO as code owners September 10, 2026 23:12

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

🔍 Devin Review: 1 flag

Not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 Dropped pumps leave threads detached

When a source remains blocked, RunningPump::drop only signals stop and detaches the join handle. The thread and captured resources can remain alive indefinitely.

1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

@knope-bot
knope-bot Bot force-pushed the knope/release branch 7 times, most recently from cc8f388 to 3414f91 Compare September 18, 2026 19:27
@knope-bot
knope-bot Bot requested a review from 1egoman as a code owner September 20, 2026 17:24

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 1 new potential issue.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

name = "livekit-datatrack"
description = "Data track core for LiveKit"
version = "0.1.15"
version = "0.1.16"

@devin-ai-integration devin-ai-integration Bot Sep 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Patch release breaks Rust consumers

A ^0.1.15 dependency can resolve 0.1.16, but both error Failed variants changed from unit to struct variants. Existing Rust consumers then fail to compile after a compatible update.

Learn more

Cargo treats releases within 0.1.x as semver-compatible. The error variants are public through the crate's backend API, and changing a unit variant to a struct variant breaks both construction and pattern matching. A resolver can therefore upgrade existing consumers automatically and hand them source that no longer compiles.

Example: A consumer declaring livekit-datatrack = "0.1.15" and matching EncryptionError::Failed can receive 0.1.16 during a lockfile update. Its unchanged match no longer compiles because the variant now requires { reason }.

Recommended fix: Release livekit-datatrack as 0.2.0 and update the workspace dependency and every generated release reference accordingly. Alternatively, preserve the existing Rust variant shape while introducing a separate UniFFI-facing error type.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 Engine drop leaves signaling alive

Dropping RtcEngine lets engine_task release the engine without closing its session. The detached signal task retains the websocket until the server disconnects.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants