Commit Graph
7759 Commits
Author SHA1 Message Date
jared 576c80a989 Merge pull request 'feat(denoise): switch noise suppression mid-call (+ fix re-captures ignoring noiseSuppression)' (#66) from feat/live-denoise-switch into lotus
CI / Build embedded bundle (push) Successful in 2m9s
CI / Publish to Gitea npm registry (push) Successful in 50s
v0.28.0-lotus.4
2026-10-30 21:15:44 -04:00
Lotus CIandClaude Opus 5.5 949103d649 feat(denoise): switch noise suppression mid-call (io.lotus.set_denoise)
CI / Build embedded bundle (push) Skipped
CI / Build embedded bundle (pull_request) Successful in 1m47s
CI / Publish to Gitea npm registry (pull_request) Skipped
The host can now change noise suppression on the live mic without a
rejoin: off / browser-native / ML, the ML model, the gate and stacking
browser NS in front of the model.

- Model swaps preload the new model while the old one keeps running,
  then swap the processor (no mic re-capture).
- Browser NS on/off re-captures the mic via restartTrack with the new
  constraint (passing the deviceId, without which LiveKit drops every
  constraint). The choice is kept in lotusCaptureOverride, which
  ConnectionFactory reads, so a later SFU reconnect captures the same way.
- Switches are serialized; a burst collapses into the last one. Each one
  reports io.lotus.denoise_state (now with `mode`).

Fixes found while testing in Chromium:
- The mic level meter (and muted-speech nudge) kept a clone of the
  ORIGINAL mic track and never noticed LiveKit's restartTrack. Chrome
  makes all open tracks of a device share audio processing, so every
  re-capture silently kept the old noiseSuppression (asked false, got
  true). The meter now drops its clone around our re-capture and
  re-taps on TrackEvent.Restarted, which also fixes it listening to the
  old device after a mic switch.
- LiveKit defaults voiceIsolation ON, a further voice filter in "off"
  and ML modes where the platform implements it. It now follows browser
  noise suppression.

Verified in a two-browser call: joined as browser and as ML(dtln), then
switched dtln -> deepfilternet -> rnnoise -> browser -> off; each step
applied within ~0.5 s and every re-capture got the constraints it asked
for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-30 21:13:40 -04:00
jared 9e6fe75f14 Merge pull request 'fix(denoise): DeepFilterNet attenuation limit 60 → 25 dB (choppy word endings)' (#65) from fix/dfn-strength-25 into lotus
CI / Build embedded bundle (push) Successful in 5m59s
CI / Publish to Gitea npm registry (push) Successful in 4m12s
v0.28.0-lotus.3
2026-10-30 18:58:29 -04:00
Lotus CIandClaude Opus 5.5 f180f76196 fix(denoise): DeepFilterNet attenuation limit 60 -> 25 dB
CI / Build embedded bundle (push) Skipped
CI / Build embedded bundle (pull_request) Successful in 8m5s
CI / Publish to Gitea npm registry (pull_request) Skipped
At 60 dB the background is muted outright (measured -61 to -64 dB), so
each word drops into dead silence and listeners hear the mic cutting out
at word ends. On room-echo speech (RT60 ~0.4 s) with fan and keyboard
noise at SNR 15 dB, 25 dB scored best:

  limit  PESQ clean/fan/keyboard   noise removed
  60     3.35 / 2.33 / 2.04        ~62 dB
  40     3.41 / 2.45 / 2.21        32-40 dB
  25     3.59 / 2.72 / 2.38        25 dB
  20     3.63 / 2.66 / 2.25        20 dB

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-30 18:50:06 -04:00
jared 4ca3b0695c Merge pull request 'fix(denoise): stop DeepFilterNet silently passing raw audio through' (#64) from fix/dfn-model-bytes into lotus
CI / Build embedded bundle (push) Successful in 8m41s
CI / Publish to Gitea npm registry (push) Skipped
2026-10-30 15:16:25 -04:00
Lotus CIandClaude Opus 5.5 283b231c7a style: oxfmt
CI / Build embedded bundle (push) Skipped
CI / Build embedded bundle (pull_request) Successful in 5m2s
CI / Publish to Gitea npm registry (pull_request) Skipped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-30 15:11:19 -04:00
Lotus CIandClaude Opus 5.5 16f5f3d1a3 fix(denoise): stop DeepFilterNet silently passing raw audio through
CI / Build embedded bundle (push) Skipped
CI / Build embedded bundle (pull_request) Failing after 5m38s
CI / Publish to Gitea npm registry (pull_request) Skipped
If the DeepFilterNet model is served with `Content-Encoding: gzip` (vite
preview does this for .tar.gz; some CDNs and nginx gzip_static setups do
too), fetch() hands back the already-unpacked tar. The library's worklet
then fails inside df_create, swallows the error and passes the raw mic
through, while Lotus Call reports DeepFilterNet as active.

Check the bytes after initialize(): a gzip model is used as-is, an
unpacked tar is re-gzipped in the browser, and anything else throws so
the rnnoise fallback runs and the host is told the truth.

Measured in a two-browser call (fan noise, SNR 15 dB): before, 4.9 dB of
noise removed, i.e. none beyond gain differences; after, 30.9 dB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-30 14:18:01 -04:00
jared 117467b1fb Merge pull request 'chore(deps): security fixes for dev/build tooling (Storybook, Vitest, Vite, transitive)' (#63) from chore/dev-tool-security into lotus
CI / Build embedded bundle (push) Successful in 5m37s
CI / Publish to Gitea npm registry (push) Skipped
2026-10-25 23:59:03 -04:00
Lotus CIandClaude Opus 5.5 43cbd8409d chore(deps): security fixes for dev/build tooling (Storybook, Vitest, Vite, transitive)
CI / Build embedded bundle (push) Skipped
CI / Build embedded bundle (pull_request) Successful in 4m6s
CI / Publish to Gitea npm registry (pull_request) Skipped
The npm advisory database flagged 19 packages in pnpm-lock.yaml. None of them
ship in the embedded call bundle (checked against the built dist); they run
on developer machines and in CI:
- storybook / @storybook/* 10.6.0 -> 10.6.3: critical, dev server code
  injection from the local network.
- vitest 4.1.12 (+ @vitest/ui unpinned to ^4.1.12), tinypool ^2.1.2:
  mock registration code injection, prototype-pollution RCE.
- vite ^8.3.5: dev-server file exposure, launch-editor issues.
- Overrides for transitive tooling: brace-expansion, browserslist,
  smol-toml, source-map-js, postcss-selector-parser, baseline-browser-
  mapping, fflate, pbkdf2, zod 4; existing qs/js-yaml/undici/dompurify
  overrides raised to the fixed versions.

Left: elliptic (no fixed release, low), zod 3 (no 3.x fix; a dependency
pins it). Lotus unit tests 144/144, build:embedded OK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-25 23:50:09 -04:00
jared 4c84c3a4f3 Merge pull request 'feat(lotus): expected-device check before joining (cinny #121)' (#62) from feat/expected-devices into lotus
CI / Build embedded bundle (push) Successful in 4m12s
CI / Publish to Gitea npm registry (push) Successful in 1m32s
v0.28.0-lotus.2
2026-10-24 19:47:38 -04:00
Lotus CIandClaude Opus 5.5 a366243836 feat(lotus): expected-device check before joining (cinny #121)
CI / Build embedded bundle (push) Skipped
CI / Build embedded bundle (pull_request) Successful in 4m21s
CI / Publish to Gitea npm registry (pull_request) Skipped
EC remembers the picked mic / output by id and silently falls back to the
first device when it is missing, so a user who always joins with a headset
lands on the laptop mic. With lotusDeviceCheck=1:
- the last-picked device's NAME is remembered next to its id
  (lotus-audio-{input,output}-name), since ids can change on re-plug;
- before the automatic join, a usual device that is gone is reported to the
  host (io.lotus.device_missing) and EC waits for io.lotus.device_decision
  { join }; one that came back under a new id is just re-selected;
- in a call, losing it is reported (io.lotus.device_lost) for a toast.
Fails open (no names / no host / nothing remembered). Without the flag the
join stays synchronous, as upstream. The gate runs once per call: CallView's
effect re-runs while its inputs settle and must not restart it.

Embedded version 0.28.0-lotus.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-24 19:42:23 -04:00
jared 83a700b7f6 Merge pull request 'merge: upstream Element Call v0.28.0 (cinny #201)' (#61) from lotus-upstream-v0.28.0 into lotus
CI / Build embedded bundle (push) Successful in 3m48s
CI / Publish to Gitea npm registry (push) Successful in 56s
v0.28.0-lotus.1
2026-10-24 01:14:31 -04:00
Lotus CIandClaude Opus 5.5 fc15193715 merge: upstream Element Call v0.28.0 into lotus (cinny #201)
CI / Build embedded bundle (push) Skipped
CI / Build embedded bundle (pull_request) Successful in 4m21s
CI / Publish to Gitea npm registry (pull_request) Skipped
Syncs the fork from upstream v0.25.0 to v0.28.0 (196 upstream commits;
v0.27 was skipped upstream), bringing matrix-js-sdk develop up to the
SDK 44 MatrixRTC changes (livekit_alias / oldest_membership removed),
delayed-leave delegation to the SFU, and the HostBridge host interface.

Lotus changes carried across the refactors:
- widget: upstream no longer exports a widget singleton (initializer hands
  initializeWidget()'s result to React). The Lotus host integration
  (src/lotus/*) reads `widget` at call time, so a Lotus-only exported
  reference is set by initializeWidget.
- useTheme: theme classes now go on the root element (the body in the
  widget build); the lotusTheme / lotusTransparent / lotusHostControls
  classes follow it.
- LocalMember: [lotus #46] keep retrying network errors until the delayed
  leave would fire (Math.max), on upstream's restructured timings.
- UrlConfiguration moved to its own file; autoGainControl moved with it.
- errors: upstream switched to i18n.t; SFUTokenRefusedError follows.
- keyboard shortcuts: Lotus host hotkeys still win over focusIsClaimed().
- GroupCallErrorBoundary: the reconnect handler uses the widget reference
  (upstream dropped the widget prop).

Config: v0.26 renamed matrix_rtc_session.delayed_leave_event_* to
delayed_leave.{delay_ms,restart_ms,restart_timeout_ms} with no fallback,
and the embedded build no longer emits a config.json. The production
config (public/element-call/config.json on LXC 106, not in git) must move
to the new keys when this ships, or calls lose the 60 s grace (lotus #46).

Embedded version 0.28.0-lotus.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-24 01:07:58 -04:00
Lotus CIandClaude Opus 5.5 3998425cdf chore(lotus): 0.25.0-lotus.29
CI / Build embedded bundle (push) Successful in 2m41s
CI / Publish to Gitea npm registry (push) Successful in 1m44s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
v0.25.0-lotus.29
2026-10-20 19:49:30 -04:00
jared 72d307df18 Merge pull request 'feat(lotus): detailed call summary for the host (cinny #253)' (#60) from feat/call-summary-details into lotus
CI / Build embedded bundle (push) Canceled after 50s
CI / Publish to Gitea npm registry (push) Canceled after 0s
2026-10-20 19:48:35 -04:00
Lotus CIandClaude Opus 5.5 a951e5b1f2 feat(lotus): detailed call summary for the host's Details card (cinny #253)
CI / Build embedded bundle (pull_request) Successful in 3m1s
CI / Publish to Gitea npm registry (pull_request) Skipped
io.lotus.call_summary gains an optional `details`: the other Matrix users
seen and the peak in the call; how long your connection, each other
person's, and everyone at once (likely the server) was poor/lost; RTT
median/p95, outbound and inbound packet loss and jitter (sampled every 5 s
from LiveKit sender/receiver stats); and your talk, mute and screenshare
time. People already present when you connect are recorded on Connected
(LiveKit sends no ParticipantConnected for them), and joins are idempotent
per device. Older hosts ignore the field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-20 19:45:02 -04:00
Lotus CIandClaude Opus 5.5 438d09cde9 chore(lotus): 0.25.0-lotus.28
CI / Build embedded bundle (push) Successful in 2m15s
CI / Publish to Gitea npm registry (push) Successful in 1m8s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
v0.25.0-lotus.28
2026-10-19 23:36:30 -04:00
jared 0534fa393c Merge pull request 'feat(lotus): soundboard works in voice channels with a call policy (#47)' (#59) from feat/soundboard-mic-mix into lotus
CI / Build embedded bundle (push) Canceled after 0s
CI / Publish to Gitea npm registry (push) Canceled after 0s
2026-10-19 23:36:00 -04:00
Lotus CIandClaude Opus 5.5 e12b3e5979 style(lotus): format LOTUS.md table
CI / Build embedded bundle (pull_request) Successful in 1m41s
CI / Publish to Gitea npm registry (pull_request) Skipped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-19 23:30:56 -04:00
Lotus CIandClaude Opus 5.5 657271163f feat(lotus): soundboard works in voice channels with a call policy (#47)
CI / Build embedded bundle (pull_request) Failing after 1m1s
CI / Publish to Gitea npm registry (pull_request) Skipped
Clips publish as a separate Unknown-source track, which tokens limited to
listed sources (any room with io.lotus.room_quality) refuse, so #52 could
only answer not_permitted. Where the token allows the microphone, the
clip is now mixed into the published mic for its duration: the track on
the mic's RTCRtpSender (post-denoise) and the clip feed a
MediaStreamAudioDestinationNode, the sender switches to the mix with
replaceTrack, and the original goes back when the clip ends. Muting
mid-clip stops it; a track LiveKit swapped in meanwhile is left alone.
not_permitted remains for tokens without the microphone.

Fixes #47

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-19 23:23:06 -04:00
Lotus CIandClaude Opus 5.5 60398b0a7d chore(lotus): 0.25.0-lotus.27
CI / Build embedded bundle (push) Successful in 2m0s
CI / Publish to Gitea npm registry (push) Successful in 52s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
v0.25.0-lotus.27
2026-10-19 15:06:39 -04:00
jared 2c8d20ba82 Merge pull request 'feat(lotus): keep your own tile on mobile with the camera off (cinny #265)' (#58) from feat/mobile-self-tile into lotus
CI / Build embedded bundle (push) Successful in 1m52s
CI / Publish to Gitea npm registry (push) Skipped
2026-10-19 14:58:35 -04:00
Lotus CIandClaude Opus 5.5 fbf8e44276 feat(lotus): keep your own tile on mobile with the camera off (cinny #265)
CI / Build embedded bundle (pull_request) Successful in 1m57s
CI / Publish to Gitea npm registry (pull_request) Skipped
Upstream drops the local PiP in the one-on-one mobile layout whenever the
local camera is off. In Lotus voice rooms that is nearly always, so on a
phone you never saw yourself or your own speaking ring. Show it as the
desktop layout does; the tile falls back to your avatar. Tests updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-19 14:40:25 -04:00
jared 5693e81bb9 Merge pull request 'feat(lotus): report remote screenshare audio to the host (cinny #277)' (#57) from feat/screenshare-audio-state into lotus
CI / Build embedded bundle (push) Successful in 1m57s
CI / Publish to Gitea npm registry (push) Skipped
2026-10-19 14:28:57 -04:00
Lotus CIandClaude Opus 5.5 5f4844cad5 feat(lotus): report remote screenshare audio to the host (cinny #277)
CI / Build embedded bundle (pull_request) Successful in 1m55s
CI / Publish to Gitea npm registry (pull_request) Skipped
New fromWidget action io.lotus.screenshare_audio_state { present }: each
LivekitRoomAudioRenderer reports whether a remote participant's
ScreenShareAudio track is being received; the combined answer is sent to
the host on change, and cleared when a renderer unmounts. cinny uses it to
show "Mute Screenshare Audio" only when there is something to mute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-19 14:21:52 -04:00
Lotus CIandClaude Opus 5.5 848dcaafa9 chore(lotus): 0.25.0-lotus.26
CI / Build embedded bundle (push) Successful in 1m55s
CI / Publish to Gitea npm registry (push) Successful in 1m0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
v0.25.0-lotus.26
2026-10-19 12:41:55 -04:00
jared 1ad32e56c7 Merge pull request 'feat(lotus): accept decorations from chat.lotusguild.org (matrix #22)' (#56) from feat/decorations-origin into lotus
CI / Build embedded bundle (push) Canceled after 1m46s
CI / Publish to Gitea npm registry (push) Canceled after 0s
2026-10-19 12:40:07 -04:00
Lotus CIandClaude Opus 5.5 090edc5c2c feat(lotus): accept decorations from chat.lotusguild.org (matrix #22)
CI / Build embedded bundle (pull_request) Successful in 1m42s
CI / Publish to Gitea npm registry (pull_request) Skipped
Decorations moved off Nextcloud to https://chat.lotusguild.org/decorations.
Add that origin to ALLOWED_DECORATION_ORIGINS (first, so tests use it);
keep drive.lotusguild.org until no host build points there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-19 12:37:53 -04:00
jared dbf77cdc60 Merge pull request 'docs(lotus): LOTUS.md lists io.lotus.call_error and io.lotus.reconnect (#50)' (#55) from docs/lotus-call-error into lotus
CI / Build embedded bundle (push) Successful in 2m8s
CI / Publish to Gitea npm registry (push) Skipped
2026-10-19 01:36:12 -04:00
Lotus CIandClaude Opus 5.5 2ef80cef2c docs(lotus): LOTUS.md lists io.lotus.call_error and io.lotus.reconnect (#50)
CI / Build embedded bundle (pull_request) Successful in 2m1s
CI / Publish to Gitea npm registry (pull_request) Skipped
Regenerate the action table from lotusActions.ts: add the two actions
from #50, and note which cinny PR handles each one still in flight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-19 00:01:18 -04:00
Lotus CIandClaude Opus 5.5 88c648ba8b chore(lotus): 0.25.0-lotus.25
CI / Build embedded bundle (push) Successful in 2m35s
CI / Publish to Gitea npm registry (push) Successful in 55s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
v0.25.0-lotus.25
2026-10-18 15:27:50 -04:00
jared 0aa543cc7d Merge pull request 'docs(lotus): LOTUS.md: the io.lotus.* widget protocol, URL flags and release flow (#43)' (#53) from docs/lotus-protocol into lotus
CI / Build embedded bundle (push) Successful in 3m6s
CI / Publish to Gitea npm registry (push) Skipped
2026-10-18 07:49:15 -04:00
jared cc57292bf4 Merge pull request 'fix(lotus): soundboard says "not permitted" in audio-only rooms instead of failing silently (#47)' (#52) from lotus-soundboard-not-permitted into lotus
CI / Build embedded bundle (push) Canceled after 0s
CI / Publish to Gitea npm registry (push) Canceled after 0s
2026-10-18 07:42:09 -04:00
jared 22f9083768 Merge pull request 'fix(lotus): restart the shared mic sampler only when the LiveKit rooms change (#45)' (#51) from lotus-mic-sampler-churn into lotus
CI / Build embedded bundle (push) Canceled after 0s
CI / Publish to Gitea npm registry (push) Canceled after 0s
2026-10-18 07:38:41 -04:00
jared d7d75cbba5 Merge pull request 'feat(lotus): tell the host when the call drops, and let it press Reconnect (cinny #318)' (#50) from lotus-call-error into lotus
CI / Build embedded bundle (push) Canceled after 0s
CI / Publish to Gitea npm registry (push) Canceled after 0s
2026-10-18 07:32:17 -04:00
jared 4be3e92eb6 Merge pull request 'fix(lotus): a homeserver stall shorter than the delayed-leave window no longer ends the call (#46)' (#54) from lotus-stall-retry into lotus
CI / Build embedded bundle (push) Canceled after 0s
CI / Publish to Gitea npm registry (push) Canceled after 0s
2026-10-18 04:52:15 -04:00
Lotus CIandClaude Opus 5.5 a1dd0e254c fix(lotus): a homeserver stall shorter than the delayed-leave window no longer ends the call (#46)
CI / Build embedded bundle (pull_request) Successful in 3m33s
CI / Publish to Gitea npm registry (pull_request) Skipped
maximumNetworkErrorRetryCount was sized to min(sync grace period,
leave delay), i.e. 10 s, so the membership manager gave up 20-35 s into
a homeserver stall and showed "Connection lost", even when the server
would keep the membership for 60 s (prod config). Size it to the leave
delay instead: the embedded call has no /sync loop for the grace period
to describe, and the server's delayed leave is what actually ends the
membership.

Fixes #46

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-18 02:47:36 -04:00
Lotus CIandClaude Opus 5.5 167ffc2440 docs(lotus): LOTUS.md: the io.lotus.* widget protocol, URL flags and release flow (#43)
CI / Build embedded bundle (pull_request) Successful in 4m5s
CI / Publish to Gitea npm registry (pull_request) Skipped
Everything the host relies on was documented only in src/lotus comments.
Add a table of the 22 io.lotus.* actions (generated from lotusActions.ts,
with direction, payload and whether cinny handles each), the URL flags,
fork-only behaviour and the release/publish steps.

Fixes #43

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-18 01:24:22 -04:00
Lotus CIandClaude Opus 5.5 888ed1a66c fix(lotus): soundboard says "not permitted" in audio-only rooms instead of failing silently (#47)
CI / Build embedded bundle (pull_request) Successful in 3m20s
CI / Publish to Gitea npm registry (pull_request) Skipped
Clips publish as an Unknown-source track. In audio-only rooms the guard
signs a microphone-only token, LiveKit refuses the publish, and since
the fork had already replied {} the host never heard. Check the grants
up front and reply { played: false, reason: "not_permitted" }.

Refs #47

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-18 01:22:49 -04:00
Lotus CIandClaude Opus 5.5 73bf2133dc fix(lotus): restart the shared mic sampler only when the LiveKit rooms change (#45)
CI / Build embedded bundle (pull_request) Successful in 3m16s
CI / Publish to Gitea npm registry (pull_request) Skipped
observeLocalMicSample$ switchMapped on every allConnections$ emission,
which re-emits far more often than the set of rooms changes. Each one
stopped the clone, closed the AudioContext and emitted null, and the
null reset the muted-speech gate, so the "You're muted" nudge could
never stay true long enough to fire. Map to the room list and only
restart when it actually changes.

Fixes #45

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-18 01:17:06 -04:00
Lotus CIandClaude Opus 5.5 07e1506dd8 feat(lotus): tell the host when the call drops, and let it press Reconnect (cinny #318)
CI / Build embedded bundle (pull_request) Successful in 3m2s
CI / Publish to Gitea npm registry (pull_request) Skipped
After a homeserver stall the frame shows "Connection lost · Reconnect"
while the host kept showing the call as joined, with controls that did
nothing. While the error page is up, report io.lotus.call_error
{ code, recoverable } (and { code: null } when it clears), and accept
io.lotus.reconnect to run the page's own Reconnect / Try again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-18 00:54:48 -04:00
Lotus CIandClaude Opus 5.5 58625c86b0 chore(lotus): 0.25.0-lotus.24
CI / Build embedded bundle (push) Successful in 3m14s
CI / Publish to Gitea npm registry (push) Successful in 1m19s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
v0.25.0-lotus.24
2026-10-17 20:47:48 -04:00
jared e3ac9a96d6 Merge pull request 'feat(lotus): report the frame's audio outputs to the host (cinny #310)' (#49) from fix/audio-output-list into lotus
CI / Build embedded bundle (push) Canceled after 0s
CI / Publish to Gitea npm registry (push) Canceled after 0s
2026-10-17 20:45:10 -04:00
Lotus CIandClaude Opus 5.5 34d541b707 feat(lotus): report the frame's audio outputs to the host (cinny #310)
CI / Build embedded bundle (pull_request) Successful in 3m28s
CI / Publish to Gitea npm registry (pull_request) Skipped
Browsers hash deviceIds per frame/origin, so ids from the host's own
enumerateDevices() are unknown in here and select() fell back to the
default. io.lotus.audio_output_state now also carries
available: [{id,label}] (frame-valid ids), so the host's call-bar menu
can offer real choices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-17 19:48:33 -04:00
Lotus CIandClaude Opus 5.5 eb59fd5b3f chore(lotus): 0.25.0-lotus.23
CI / Build embedded bundle (push) Successful in 2m51s
CI / Publish to Gitea npm registry (push) Successful in 1m9s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
v0.25.0-lotus.23
2026-10-17 17:53:24 -04:00
jared fea233f5e1 Merge pull request 'feat(lotus): sendNotificationType=none turns the call-start notification off (cinny #295)' (#48) from lotus-notify-none into lotus
CI / Build embedded bundle (push) Successful in 3m18s
CI / Publish to Gitea npm registry (push) Skipped
2026-10-16 23:13:46 -04:00
Lotus CIandClaude Opus 5.5 93905c5bc1 feat(lotus): sendNotificationType=none turns the call-start notification off (cinny #295)
CI / Build embedded bundle (pull_request) Successful in 3m55s
CI / Publish to Gitea npm registry (pull_request) Skipped
The widget intent presets default sendNotificationType to "notification",
and the URL param could only switch it to ring/notification, so the host
had no way to say "don't notify". In persistent voice channels and space
rooms that notification carries an @room mention: every member got a
highlighted ping (and phone push) whenever a moderator joined first, and
other clients showed it as a missed call.

`sendNotificationType=none` now clears it after the presets are applied.
Unit test added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
2026-10-16 22:06:12 -04:00
renovate[bot] 9b3c3569ec Update ghcr.io/element-hq/element-web:develop Docker digest to 39c94f0 (#4327)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-06 02:57:18 +00:00
Johannes Marbach a4654d9d00 Merge pull request #4315 from element-hq/johannes/workflow-call
Allow workflow_call on lint and test workflows
2026-10-05 14:07:07 +02:00
Johannes Marbach 6e5f71c796 Revert back to negative flags 2026-10-05 13:53:52 +02:00