mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
chore(attachments): hygiene sweep — dead code, stale comments, SDK type, pdf nit
- Remove the unused PerceptionUnavailableError (never raised/caught/imported). - Reword the now-shipped 'Phase 3' placeholder comments on the Anthropic + OpenAI-Responses audio paths to describe the live upstream STT/perception fallback (these placeholders are defensive, not pending work). - Clarify the no-vision image fall-through comment (fires when perception is unconfigured OR can't see, not only the former). - Type AttachmentInfo.kind as the image|text|pdf|audio union in the TS SDK. - extract_pdf_text: append the truncation marker only when there's actual text, so a scanned PDF over the page cap returns '' (-> placeholder) instead of a content-free document part.
This commit is contained in:
@@ -96,8 +96,7 @@ export interface AttachmentInfo {
|
||||
filename: string;
|
||||
mime_type: string;
|
||||
size_bytes: number;
|
||||
/** "image", "text", "pdf", or "audio". */
|
||||
kind: string;
|
||||
kind: "image" | "text" | "pdf" | "audio";
|
||||
}
|
||||
|
||||
export type UploadAttachmentResponse = AttachmentInfo;
|
||||
|
||||
@@ -54,7 +54,10 @@ def extract_pdf_text(data: bytes) -> str:
|
||||
textpage.close()
|
||||
page.close()
|
||||
text = "\n\n".join(p.strip() for p in parts if p.strip())
|
||||
if truncated:
|
||||
# Only annotate truncation when there's actual text — otherwise a scanned
|
||||
# (no text layer) PDF over the page cap would return just the marker, i.e.
|
||||
# a content-free document part. Empty stays empty → caller placeholders it.
|
||||
if truncated and text:
|
||||
text += f"\n\n[PDF truncated at {_MAX_PAGES} pages]"
|
||||
return text
|
||||
except Exception as exc:
|
||||
|
||||
@@ -50,10 +50,6 @@ _DESCRIBE_PROMPT = (
|
||||
)
|
||||
|
||||
|
||||
class PerceptionUnavailableError(RuntimeError):
|
||||
"""No usable perception backend is configured/resolvable (maps to a placeholder)."""
|
||||
|
||||
|
||||
class PerceptionBackendError(RuntimeError):
|
||||
"""A configured perception backend failed during the perceive call."""
|
||||
|
||||
|
||||
@@ -692,9 +692,10 @@ class AnthropicProvider:
|
||||
converted.append(block)
|
||||
continue
|
||||
if part.get("type") == "input_audio":
|
||||
# Anthropic has no audio-input API. Phase 3 transcribes via the
|
||||
# STT role upstream of this translator; until then surface a
|
||||
# placeholder rather than passing an unsupported block to the API.
|
||||
# Anthropic has no audio-input API. The STT-role fallback runs
|
||||
# upstream of this translator (audio → text transcript when a
|
||||
# model lacks supports_audio_input), so by here any remaining
|
||||
# input_audio is a defensive placeholder, not the live path.
|
||||
converted.append(
|
||||
{"type": "text", "text": "[audio attachment — not supported by this model]"}
|
||||
)
|
||||
|
||||
@@ -84,9 +84,10 @@ def convert_content_parts(parts: list[Any]) -> list[dict[str, Any]]:
|
||||
}
|
||||
)
|
||||
elif ptype == "input_audio":
|
||||
# Audio-input is not wired on the Responses lane; until the Phase 3
|
||||
# capability-gated fallback (STT) lands upstream, surface a
|
||||
# placeholder rather than leaking an unhandled part to the API.
|
||||
# Audio-input is not wired on the Responses lane. The capability-gated
|
||||
# fallback (STT / perception) runs upstream of this translator, so by
|
||||
# here any remaining input_audio is a defensive placeholder rather than
|
||||
# an unhandled part leaking to the API.
|
||||
converted.append(
|
||||
{"type": "input_text", "text": "[audio attachment — not supported by this model]"}
|
||||
)
|
||||
|
||||
@@ -3015,8 +3015,9 @@ class ChatSession:
|
||||
perceived = self._perception_fallback_part(att, "image")
|
||||
if perceived is not None:
|
||||
return perceived
|
||||
# No perception backend configured: emit the native image_url
|
||||
# unchanged (the model may ignore it) — pre-existing behavior.
|
||||
# No usable perception backend (none configured, or it can't see):
|
||||
# emit the native image_url unchanged — a no-vision model ignores it.
|
||||
# Image is intentionally left ungated here (pre-existing behavior).
|
||||
if kind == "audio" and not caps.supports_audio_input:
|
||||
return self._audio_fallback_part(att)
|
||||
return attachment_to_content_part(att)
|
||||
|
||||
Reference in New Issue
Block a user