fix: improve media failure diagnostics and token fallback coverage
This commit is contained in:
@@ -435,9 +435,9 @@ class SlackChannel(BaseChannel):
|
||||
marker = f"[{marker_type}: {name}]"
|
||||
url = str(file_info.get("url_private_download") or file_info.get("url_private") or "")
|
||||
if not url:
|
||||
return None, f"[{marker_type}: {name}: missing download url]"
|
||||
return None, self._download_failure_marker(marker_type, name, "missing download url")
|
||||
if not self.config.bot_token:
|
||||
return None, f"[{marker_type}: {name}: missing bot token]"
|
||||
return None, self._download_failure_marker(marker_type, name, "missing bot token")
|
||||
|
||||
filename = safe_filename(f"{file_id}_{name}")
|
||||
path = Path(get_media_dir("slack")) / filename
|
||||
@@ -454,7 +454,14 @@ class SlackChannel(BaseChannel):
|
||||
return str(path), marker
|
||||
except Exception as e:
|
||||
logger.warning("Failed to download Slack file {}: {}", file_id, e)
|
||||
return None, f"[{marker_type}: {name}: download failed]"
|
||||
return None, self._download_failure_marker(marker_type, name, "download failed")
|
||||
|
||||
@staticmethod
|
||||
def _download_failure_marker(marker_type: str, name: str, reason: str) -> str:
|
||||
return (
|
||||
f"[{marker_type}: {name}: {reason}; not available to nanobot. "
|
||||
"Check Slack files:read scope, reinstall the Slack app, and ensure the bot can access the file.]"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _looks_like_html_download(response: httpx.Response) -> bool:
|
||||
|
||||
@@ -643,6 +643,14 @@ def test_slack_download_rejects_login_html() -> None:
|
||||
assert SlackChannel._looks_like_html_download(markdown_response) is False
|
||||
|
||||
|
||||
def test_slack_download_failure_marker_is_actionable() -> None:
|
||||
marker = SlackChannel._download_failure_marker("image", "screenshot.png", "download failed")
|
||||
|
||||
assert "not available to nanobot" in marker
|
||||
assert "files:read" in marker
|
||||
assert "reinstall the Slack app" in marker
|
||||
|
||||
|
||||
def test_slack_channel_uses_channel_aware_allow_policy() -> None:
|
||||
channel = SlackChannel(SlackConfig(enabled=True, allow_from=[]), MessageBus())
|
||||
assert channel.is_allowed("U1") is True
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
from nanobot.utils.helpers import estimate_prompt_tokens_chain
|
||||
|
||||
|
||||
class _NoCounterProvider:
|
||||
pass
|
||||
|
||||
|
||||
class _BrokenCounterProvider:
|
||||
def estimate_prompt_tokens(self, messages, tools=None, model=None):
|
||||
raise RuntimeError("counter unavailable")
|
||||
|
||||
|
||||
def test_estimate_prompt_tokens_chain_falls_back_without_provider_counter() -> None:
|
||||
tokens, source = estimate_prompt_tokens_chain(
|
||||
_NoCounterProvider(),
|
||||
"test-model",
|
||||
[{"role": "user", "content": "hello"}],
|
||||
)
|
||||
|
||||
assert tokens > 0
|
||||
assert source == "tiktoken"
|
||||
|
||||
|
||||
def test_estimate_prompt_tokens_chain_falls_back_when_provider_counter_fails() -> None:
|
||||
tokens, source = estimate_prompt_tokens_chain(
|
||||
_BrokenCounterProvider(),
|
||||
"test-model",
|
||||
[{"role": "user", "content": "hello"}],
|
||||
)
|
||||
|
||||
assert tokens > 0
|
||||
assert source == "tiktoken"
|
||||
Reference in New Issue
Block a user