3 Commits
Author SHA1 Message Date
HomerandClaude Opus 5.5 8f04494ba8 LLeMbas Desktop 0.7.1, re-released: the fix folded in, no 0.7.2
ci / check (push) Failing after 3s
release / linux (push) Failing after 3s
The first 0.7.1 aborted on Linux before its window appeared (it read
WebKitWebView's write-only 'settings' property). The owner asked for the
patch to be released again rather than followed by a 0.7.2: this commit is
0.7.1 as it should have been, and tag v0.7.1 moves here. The release
workflow now replaces the release of a tag that is pushed again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 22:40:43 +00:00
HomerandClaude Opus 5.5 8062a8ac77 LLeMbas Desktop 0.7.2: starts again on Linux
release / linux (push) Failing after 3s
ci / check (push) Failing after 3s
0.7.1 read WebKitWebView's 'settings' property through GLib; it is write-only,
GLib panicked, and the app aborted before its window appeared. The read is
gone; the microphone permission handler stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 22:39:32 +00:00
HomerandClaude Opus 5.5 4a982ae089 LLeMbas Desktop 0.7.1, carrying LLeMbas CLI 1.5.1
release / linux (push) Failing after 2s
ci / check (push) Failing after 3s
The microphone: WebKitGTK refuses a permission request its app does not
answer, and has no prompt of its own, so dictation on the server's page was
always blocked. The content view now allows the microphone -- only that, and
only there -- and media capture is switched on explicitly for the older
WebKitGTK the AppImage carries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 21:28:17 +00:00
6 changed files with 45 additions and 6 deletions

No files matched your search

+3
View File
@@ -62,5 +62,8 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
git tag -l --format='%(contents)' "$TAG" | sed '/-----BEGIN SSH SIGNATURE-----/,$d' > notes.md
# A tag moved to a fixed commit and pushed again replaces its release:
# the old one, and the files built from the old commit, go first.
gh release delete "$TAG" --repo "$GITHUB_REPOSITORY" --yes 2>/dev/null || true
gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --verify-tag \
--title "LLeMbas Desktop $VERSION" --notes-file notes.md dist/*
+17
View File
@@ -6,6 +6,23 @@ All notable changes to LLeMbas Desktop. The format follows
## [Unreleased]
## [0.7.1] — 2026-10-24
The microphone works, and LLeMbas CLI 1.5.1 inside.
### Fixed
- **Dictation said the microphone was blocked, with no way to allow it.** The server's page asks
for the microphone, and a webview grants it only if the app answers: WebKitGTK refuses whatever
it is not answered on, and shows no prompt of its own. Desktop now allows the microphone -- the
microphone only, and only for the server's page in the content view; a camera or a screen still
gets the platform's refusal.
### Changed
- Carries LLeMbas CLI 1.5.1: an image counts by its size, so a screenshot no longer makes the
agent compact.
## [0.7.0] — 2026-10-20
Carries LLeMbas CLI 1.5.0: harness spec 2.0.0 — background work as jobs the person can see,
+1 -1
View File
@@ -1 +1 @@
1.5.0
1.5.1
+1 -1
View File
@@ -2064,7 +2064,7 @@ checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae"
[[package]]
name = "llembas-desktop"
version = "0.7.0"
version = "0.7.1"
dependencies = [
"gtk",
"libc",
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "llembas-desktop"
version = "0.7.0"
version = "0.7.1"
description = "LLeMbas Desktop: your LLeMbas server in a window, with the agent on this computer"
authors = ["Jaroslav Beneš"]
license = "MIT"
@@ -17,7 +17,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2", features = ["tray-icon", "unstable"] }
tauri = { version = "2.12", features = ["tray-icon", "unstable"] }
tauri-plugin-dialog = "2"
tauri-plugin-opener = "2"
tauri-plugin-single-instance = "2"
+21 -2
View File
@@ -30,7 +30,7 @@ use std::sync::Mutex;
use serde::Serialize;
use tauri::menu::{Menu, MenuItem, PredefinedMenuItem};
use tauri::tray::TrayIconBuilder;
use tauri::webview::WebviewBuilder;
use tauri::webview::{PermissionKind, PermissionResponse, WebviewBuilder};
use tauri::window::{Color, WindowBuilder};
use tauri::{
AppHandle, Emitter, LogicalPosition, LogicalSize, Manager, RunEvent, Url, Webview, WebviewUrl,
@@ -425,12 +425,14 @@ fn build_main(handle: &AppHandle, target: Option<Url>) -> tauri::Result<()> {
pin_titlebar(&bar);
}
let nav = handle.clone();
let perm = handle.clone();
window.add_child(
WebviewBuilder::new(CONTENT, url)
.user_agent(&user_agent())
.background_color(theme.background())
.initialization_script(THEME_SCRIPT)
.on_navigation(move |url| allowed(&nav, url)),
.on_navigation(move |url| allowed(&nav, url))
.on_permission_request(move |view, kind| permission(&perm, &view, kind)),
LogicalPosition::new(FRAME, FRAME + TITLE_H),
LogicalSize::new(
size.width - 2.0 * FRAME,
@@ -441,6 +443,23 @@ fn build_main(handle: &AppHandle, target: Option<Url>) -> tauri::Result<()> {
Ok(())
}
/// The server's dictation asks for the microphone, and a webview answers a permission request
/// only if its app does: WebKitGTK refuses anything it is not answered on, and has no prompt of
/// its own -- so the microphone simply said "Permission may be blocked" with no way to allow it.
/// Granted for the microphone, in the content view, once a server is chosen, and for nothing
/// else (a camera or a screen gets the platform's default, which on Linux is no). The content view
/// never shows another origin: `allowed` sends every other site to the system browser.
fn permission(handle: &AppHandle, view: &Webview, kind: PermissionKind) -> PermissionResponse {
if kind != PermissionKind::Microphone || view.label() != CONTENT {
return PermissionResponse::Default;
}
if handle.state::<App>().settings().server.is_some() {
PermissionResponse::Allow
} else {
PermissionResponse::Deny
}
}
/// On Linux, Tauri packs every webview of a window into the window's GTK box, each with an equal
/// share of the height, and positions and sizes set on a webview are not applied there. So the
/// title bar is told directly: a fixed height, no share of what is left (the content takes it).