Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a31e57f
ci: add Windows ARM64 build to GitHub Actions matrix
clementb49 Mar 13, 2026
997b978
fix(ci): fix ARM64 Windows build for cryptography dependency
clementb49 Mar 13, 2026
13a6f7a
fix(ci): install ARM64 OpenSSL via vcpkg to build cryptography
clementb49 Mar 13, 2026
3ee5b2f
feat: restrict accessible_output3 to x86/x86_64 Windows
clementb49 Mar 13, 2026
ce6a2d6
fix(ci): fix invalid arm64compatible in Inno Setup script
clementb49 Mar 13, 2026
ef20163
ci: use actions/checkout to fetch vcpkg instead of git clone
clementb49 Mar 13, 2026
112292e
fix(updater): detect ARM64 architecture for update download
clementb49 Mar 13, 2026
8a79cc3
fix: remove uv environment restriction
clementb49 Apr 11, 2026
dbbe0e1
fix: correct vcpkg build path
clementb49 Apr 11, 2026
4c4af59
feat: use vcpkg action
clementb49 Apr 11, 2026
119ab5a
fix: add missing github token
clementb49 Apr 11, 2026
5c0e009
fix: change vcpkg subdir
clementb49 Apr 11, 2026
7cb3c2d
fix: move repository checkout
clementb49 Apr 11, 2026
6dc9929
fix: use a a subdir for repo checkout
clementb49 Apr 11, 2026
638606e
fix: correct path for installer
clementb49 Apr 11, 2026
8cc1fb4
fix: correct path for windows installer spec
clementb49 Apr 11, 2026
574ea22
fix: change GITHUB_WORKSPACE env var
clementb49 Apr 11, 2026
7da9f31
fix: sppecify innosetup script as relative path
clementb49 Apr 11, 2026
901ed26
fix: use the correct sub path to upload setup
clementb49 Apr 11, 2026
a3ef151
fix: remove archive for pot file
clementb49 Apr 11, 2026
e2616d5
feat: disable workflow when only .pre-commit config file is updated
clementb49 Apr 11, 2026
a9e8df7
fix: prevent crash in handle when accessible_output3 is unavailable
clementb49 Apr 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 41 additions & 13 deletions .github/workflows/build_app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,68 +6,96 @@ permissions:

jobs:
build_windows:
runs-on: windows-2025
runs-on: ${{ matrix.runner }}
env:
UV_NO_DEV: true
strategy:
fail-fast: false
matrix:
arch:
- x86_64
- x86
include:
- arch: x86_64
runner: windows-2025
- arch: x86
runner: windows-2025
- arch: arm64
runner: windows-11-arm

steps:
- name: checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: setup uv
uses: astral-sh/setup-uv@v7
with:
python-version: 'cpython-3.14-windows-${{ matrix.arch }}-none'
- name: install OpenSSL via vcpkg (arm64)
if: matrix.arch == 'arm64'
id: vcpkg
uses: johnwason/vcpkg-action@v7
with:
pkgs: openssl
triplet: arm64-windows
token: ${{ github.token }}
- name: set OpenSSL env (arm64)
if: matrix.arch == 'arm64'
run: |
$installed = "${{ github.workspace }}\vcpkg\installed\arm64-windows"
echo "OPENSSL_DIR=$installed" >> $env:GITHUB_ENV
- name: checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
path: ${{ github.workspace }}/repo
- name: Install dependencies
run: uv sync --frozen --no-dev --group build --group test
working-directory: ${{ github.workspace }}/repo
run: uv sync --frozen --compile --group build --group test
- name: run tests
working-directory: ${{ github.workspace }}/repo
run: uv run -m pytest --cov
- name: compile translations
working-directory: ${{ github.workspace }}/repo
run: uv run setup.py compile_catalog
- name: Build executable
working-directory: ${{ github.workspace }}/repo
run: uv run -m cx_Freeze build_exe
- name: get variables
id: get_variables
working-directory: ${{ github.workspace }}/repo
run: |
$version = (uv run -m setuptools_scm)
echo version_number=$version >> $env:GITHUB_OUTPUT
if ("${{ matrix.arch }}" -eq "x86_64") {
echo arch="x64" >> $env:GITHUB_OUTPUT
} elseif ("${{ matrix.arch }}" -eq "arm64") {
echo arch="arm64" >> $env:GITHUB_OUTPUT
} else {
echo arch="x86" >> $env:GITHUB_OUTPUT
}
- name: build windows installer
uses: Minionguyjpro/Inno-Setup-Action@v1.2.7
with:
path: .\win_installer.iss
path: repo\win_installer.iss
options: |
/O+
/DAppArch=${{ steps.get_variables.outputs.arch }}
/DMyAppVersion=${{ steps.get_variables.outputs.version_number }}

- name: create user config file for portable version
working-directory: ${{ github.workspace }}/repo
run: |
New-Item -Path dist -Name user_data -ItemType directory
New-Item -Path dist\user_data -Name config.yml -ItemType file
echo "general:" >> dist\user_data\config.yml
echo " language: auto" >> dist\user_data\config.yml
echo " log_level: info" >> dist\user_data\config.yml

- name: create and upload portable zip
uses: actions/upload-artifact@v7
with:
name: portable_basiliskLLM_${{ steps.get_variables.outputs.version_number }}_${{ runner.os }}_${{ steps.get_variables.outputs.arch }}
path: dist/*
path: ${{ github.workspace }}/repo/dist/*
if-no-files-found: error
retention-days: 30
- name: upload installer
uses: actions/upload-artifact@v7
with:
name: setup_basiliskLLM_${{ steps.get_variables.outputs.version_number }}_${{ runner.os }}_${{ steps.get_variables.outputs.arch }}
path: output_setup/*
path: ${{ github.workspace }}/repo/output_setup/*
if-no-files-found: error
retention-days: 30
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ on:
- CI*
tags:
- v*
paths-ignore:
- ".pre-commit-config.yaml"
pull_request:
branches:
- master
paths-ignore:
- ".pre-commit-config.yaml"

permissions:
contents: write
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/localization.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ on:
jobs:
generate_pot:
runs-on: windows-latest
env:
UV_NO_DEV: true
permissions:
contents: read
steps:
Expand All @@ -25,7 +27,7 @@ jobs:
- name: setup uv
uses: astral-sh/setup-uv@v7
- name: Install dependencies
run: uv sync --frozen --no-dev --group build
run: uv sync --frozen --group build
- name: build POT file
run: uv run setup.py extract_messages
- name: upload POT file
Expand All @@ -35,6 +37,7 @@ jobs:
path: basiliskLLM.pot
if-no-files-found: error
retention-days: 30
archive: false

upload_on_crowdin:
runs-on: ubuntu-latest
Expand Down
36 changes: 33 additions & 3 deletions basilisk/accessible_output.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
"""Functions for interacting with the Accessible Output library."""

from __future__ import annotations

import logging
import re
from functools import cached_property
from typing import TYPE_CHECKING

try:
import accessible_output3.outputs.auto

_AO3_AVAILABLE = True
except ImportError:
_AO3_AVAILABLE = False

import accessible_output3.outputs.auto
if TYPE_CHECKING:
import accessible_output3.outputs.auto

import basilisk.config as config
from basilisk.completion_handler import COMMON_PATTERN
Expand All @@ -14,6 +25,16 @@
RE_SPEECH_STREAM_BUFFER = re.compile(rf"{COMMON_PATTERN}")


class _NullAccessibleOutput:
"""No-op fallback used when accessible_output3 is unavailable."""

def speak(self, text: str) -> None:
pass

def braille(self, text: str) -> None:
pass


class AccessibleOutputHandler:
"""Handles accessible output and streaming for screen readers.

Expand Down Expand Up @@ -55,12 +76,21 @@ def clean_steps(self) -> list[tuple[re.Pattern | str]]:

@property
def use_accessible_output(self) -> bool:
"""Check if accessible output is enabled in the configuration."""
return config.conf().conversation.use_accessible_output
"""Check if accessible output is enabled and available."""
return (
_AO3_AVAILABLE and config.conf().conversation.use_accessible_output
)

@measure_time
def _init_accessible_output(self, display_log: bool) -> None:
"""Initialize the Accessible Output library."""
if not _AO3_AVAILABLE:
if display_log:
log.debug(
"accessible_output3 is not available on this platform."
)
self._accessible_output = _NullAccessibleOutput()
return
Comment on lines +87 to +93

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.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether callers rely on Auto-specific APIs beyond speak/braille.
rg -nP --type=py '\.accessible_output\.[A-Za-z_]\w*\(' -C2

Repository: SigmaNight/basiliskLLM

Length of output: 703


🏁 Script executed:

# First, let's look at the file to understand the current type annotations
cat -n basilisk/accessible_output.py | head -120

Repository: SigmaNight/basiliskLLM

Length of output: 4350


🏁 Script executed:

# Check for any usages of accessible_output property outside this file
rg -nP --type=py 'accessible_output\.' --glob='!basilisk/accessible_output.py'

Repository: SigmaNight/basiliskLLM

Length of output: 348


🏁 Script executed:

# Also check what accessible_output3 is and what Auto provides
rg -nP --type=py 'accessible_output3|import Auto' basilisk/

Repository: SigmaNight/basiliskLLM

Length of output: 610


Fix type annotation for accessible_output property; it can return None or _NullAccessibleOutput, not just Auto.

The accessible_output property is typed as accessible_output3.outputs.auto.Auto (line 106), but can actually return None (when use_accessible_output is False; see line 99) or _NullAccessibleOutput (line 92). Both _NullAccessibleOutput and Auto provide speak() and braille() methods, which are the only methods actually called (lines 150, 158).

Use a Protocol to properly express this contract:

Proposed typing refactor
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Protocol
@@
 class _NullAccessibleOutput:
 	"""No-op fallback used when accessible_output3 is unavailable."""
 	def speak(self, text: str) -> None:
 		pass
 	def braille(self, text: str) -> None:
 		pass
+
+
+class _AccessibleOutputBackend(Protocol):
+	def speak(self, text: str) -> None: ...
+	def braille(self, text: str) -> None: ...
@@
 	def __init__(self):
 		"""Initialize the accessible output handler."""
-		self._accessible_output = None
+		self._accessible_output: _AccessibleOutputBackend | None = None
@@
-	def accessible_output(self) -> accessible_output3.outputs.auto.Auto:
+	def accessible_output(self) -> _AccessibleOutputBackend | None:
 		"""Get the Accessible Output instance, initializing it if necessary."""
 		if self._accessible_output is None:
 			self._init_accessible_output(False)
 		return self._accessible_output
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@basilisk/accessible_output.py` around lines 87 - 93, The accessible_output
property is currently annotated as accessible_output3.outputs.auto.Auto but can
also be None (when use_accessible_output is False) or an instance of
_NullAccessibleOutput; define a small Protocol (e.g., AccessibleOutputLike) that
declares the speak(...) and braille(...) methods, then change the
accessible_output property's return type to Optional[AccessibleOutputLike] (or
Union[AccessibleOutputLike, None]) so callers see the correct contract; update
imports to include typing.Protocol and Optional and use AccessibleOutputLike in
the property/type hints instead of Auto.

if not self.use_accessible_output:
if display_log:
log.warning(
Expand Down
5 changes: 4 additions & 1 deletion basilisk/updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,11 @@ def get_app_architecture(self) -> str:
"""Get the architecture of the application.

Returns:
The architecture of the application as a string (e.g., 'x64' or 'x86').
The architecture of the application as a string (e.g., 'x64', 'x86' or 'arm64').
"""
machine = platform.machine()
if machine == "ARM64":
return "arm64"
arch = platform.architecture()[0]
if arch == "64bit":
return "x64"
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ readme = "README.md"
license = "GPL-2.0-only"
requires-python = ">=3.14,<3.15"
dependencies = [
"accessible-output3 @ git+https://github.com/SigmaNight/accessible_output3.git",
"accessible-output3 @ git+https://github.com/SigmaNight/accessible_output3.git ; sys_platform == 'win32' and platform_machine != 'ARM64'",
"alembic>=1.18,<1.19",
"anthropic>=0.94.0,<0.95",
"babel>=2.17,<2.19",
Expand Down Expand Up @@ -79,6 +79,7 @@ fallback_version = "0.0.0"
[tool.uv]
package = false


[tool.coverage.run]
branch = true
source = ["basilisk"]
Expand Down
Loading
Loading