Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
ce6af0b
feat: add WeatherChat dialog (Phase 1)
Orinks Feb 10, 2026
bdcdc2e
refactor: rename WeatherChat to Weather Assistant
Orinks Feb 10, 2026
4de1667
fix: keep message input enabled during generation
Orinks Feb 10, 2026
2bca303
fix: use correct TrendInsight attributes (summary, not description)
Orinks Feb 10, 2026
85d5c17
Merge branch 'dev' into feature/weather-chat
Orinks Feb 11, 2026
01612d1
feat: US-001 - Add prismatoid as optional dependency in pyproject.toml
Orinks Feb 11, 2026
a4c2c71
feat: US-002 - Create a Prism screen reader announcement helper module
Orinks Feb 11, 2026
ba51dac
feat: US-001 - Integrate ScreenReaderAnnouncer into WeatherAssistantD…
Orinks Feb 11, 2026
5a332f7
style: apply ruff formatting to test_weather_assistant_dialog.py
Orinks Feb 11, 2026
984ff81
fix: update tests for Weather Assistant rename and Prism fallback
Orinks Feb 11, 2026
0ff1ae0
fix: only mark screen reader available when backend is running at run…
Orinks Feb 11, 2026
192dbd9
feat: make prismatoid a default dependency
Orinks Feb 11, 2026
908f851
fix: announce user messages and prefix all announcements with speaker…
Orinks Feb 11, 2026
d937154
feat: US-001 - Define weather tool schemas and tool execution registry
Orinks Feb 11, 2026
8ced036
feat: US-002 - Implement tool call loop in weather assistant dialog
Orinks Feb 11, 2026
ea0b8c2
feat: US-003 - Add location resolution for tool calls
Orinks Feb 11, 2026
edff51a
feat: US-004 - Format tool results for readable AI context
Orinks Feb 11, 2026
619f5f4
feat: US-005 - Update system prompt and add integration test
Orinks Feb 11, 2026
c5f331e
chore: update progress log for US-005
Orinks Feb 11, 2026
a7cfaab
fix: resolve CI failures from Phase 2 merge
Orinks Feb 11, 2026
5891f76
fix: keep prism mock active during ScreenReaderAnnouncer tests
Orinks Feb 11, 2026
1669019
feat: add hourly forecast and location search tools to Weather Assistant
Orinks Feb 11, 2026
af3018d
feat: add location management tools to Weather Assistant
Orinks Feb 11, 2026
9354851
feat: add query_open_meteo tool for dynamic weather queries
Orinks Feb 11, 2026
4c791d5
perf: tiered tool loading to reduce token usage
Orinks Feb 11, 2026
e8f4c55
feat: add NWS discussion tools (AFD, WPC, SPC)
Orinks Feb 11, 2026
94f1c80
fix: update tests for 11 tools (was hardcoded to 3)
Orinks Feb 11, 2026
83918ad
feat: US-002 - Add NHC tropical outlook scraping to NationalDiscussio…
Orinks Feb 11, 2026
8189221
Revert "feat: US-002 - Add NHC tropical outlook scraping to NationalD…
Orinks Feb 11, 2026
9d2a0d3
test: add coverage for extended AI tools, formatters, and tiered loading
Orinks Feb 11, 2026
4a38404
feat: US-005 - Create NationwideDiscussionDialog with tabbed layout
Orinks Feb 11, 2026
f0b7c64
fix: patch mock targets for lazy imports in ai_tools tests
Orinks Feb 11, 2026
e4fa2ce
feat: use tool-capable model for function calling requests
Orinks Feb 12, 2026
97e1753
fix: remove accidentally committed build artifacts
Orinks Feb 12, 2026
bdda13e
fix: add logging for tool call debugging
Orinks Feb 12, 2026
de2a937
fix: log tool executor availability
Orinks Feb 12, 2026
c352af6
fix: use correct app attribute weather_client (not weather_service)
Orinks Feb 12, 2026
e7a7bd4
fix: add fallback chain for tool-capable models on rate limit
Orinks Feb 12, 2026
a5dfa3c
fix: retry without tools on empty response from free models
Orinks Feb 12, 2026
94cf419
fix: respect user's model selection for tool calls
Orinks Feb 12, 2026
58c01ed
fix: use NoaaApiClient for tool executor (sync, matching interface)
Orinks Feb 12, 2026
30881ff
fix: use combined NWS + Open-Meteo client for global tool coverage
Orinks Feb 12, 2026
1294bb7
feat: add Visual Crossing fallback for global alerts in tool executor
Orinks Feb 12, 2026
d20f933
fix: retry on provider tool_calls errors, not just rate limits
Orinks Feb 12, 2026
8987e22
fix: override free router to tool-capable model when tools present
Orinks Feb 12, 2026
5f2f048
fix: don't override paid autorouter for tool calls
Orinks Feb 12, 2026
9f89de0
fix: set focus to message input when Weather Assistant opens
Orinks Feb 12, 2026
61e7dcb
Merge branch 'dev' into feature/weather-chat
Orinks Feb 12, 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
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ build = [
"pyinstaller>=6.0.0",
"pillow>=10.0.0",
]
screenreader = [
"prismatoid>=0.7.0",
]

[project.scripts]
accessiweather = "accessiweather.main:main"
Expand Down Expand Up @@ -169,4 +172,3 @@ line-ending = "auto"

[tool.ruff.lint.mccabe]
max-complexity = 15

51 changes: 51 additions & 0 deletions src/accessiweather/screen_reader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Thin wrapper around prismatoid for screen reader announcements.

Provides graceful fallback when prismatoid is not installed.
"""

import logging

logger = logging.getLogger(__name__)

try:
import prism

PRISM_AVAILABLE = True
except ImportError:
PRISM_AVAILABLE = False
logger.debug("prismatoid not installed; screen reader support disabled")


class ScreenReaderAnnouncer:
"""Announces text via screen reader using prismatoid, with graceful fallback."""

def __init__(self) -> None:
"""Initialize the announcer, acquiring a screen reader backend if possible."""
self._backend = None
if PRISM_AVAILABLE:
try:
ctx = prism.Context()
self._backend = ctx.acquire_best()
logger.info("Screen reader backend acquired: %s", self._backend)
except Exception:
logger.warning("Failed to acquire screen reader backend", exc_info=True)
self._backend = None
else:
logger.debug("prismatoid not available; announcer will be a no-op")

def announce(self, text: str) -> None:
"""Speak text via screen reader. No-op if unavailable."""
if self._backend is not None:
try:
self._backend.speak(text, interrupt=False)
except Exception:
logger.warning("Failed to announce text", exc_info=True)

def is_available(self) -> bool:
"""Return whether a screen reader backend was successfully acquired."""
return self._backend is not None

def shutdown(self) -> None:
"""Clean up resources."""
self._backend = None
2 changes: 2 additions & 0 deletions src/accessiweather/ui/dialogs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .soundpack_manager_dialog import show_soundpack_manager_dialog
from .soundpack_wizard_dialog import SoundPackWizardDialog
from .uv_index_dialog import show_uv_index_dialog
from .weather_assistant_dialog import show_weather_assistant_dialog
from .weather_history_dialog import show_weather_history_dialog

__all__ = [
Expand All @@ -22,6 +23,7 @@
"show_settings_dialog",
"show_soundpack_manager_dialog",
"show_uv_index_dialog",
"show_weather_assistant_dialog",
"show_weather_history_dialog",
"SoundPackWizardDialog",
]
Loading
Loading