80 lines
3.3 KiB
Python
80 lines
3.3 KiB
Python
"""Raycast agent definition.
|
|
|
|
Field set is the union of ``raycast_api.ChatAPI.stream`` parameters that
|
|
make sense as **per-agent defaults**. Per-request values (currently:
|
|
``temperature``) win when both are set; the rest fall back to whatever
|
|
the agent declared, then to Raycast's own defaults.
|
|
|
|
``BaseAgent.system_prompt`` maps onto Raycast's wire field
|
|
``additional_system_instructions`` (the slot the real client uses for
|
|
*content*); the wire field ``system_instructions`` stays at the Raycast
|
|
source default — ``"markdown"`` for ``AI_CHAT``, ``"plain"`` otherwise.
|
|
We don't expose that wire dichotomy to the user — they get one
|
|
conceptual "system prompt".
|
|
|
|
Excluded on purpose:
|
|
|
|
* ``buffer_id``/``message_id``/``current_date`` — per-call ephemeral
|
|
* ``provider`` override — escape hatch for non-catalog models, no clear
|
|
use case yet (revisit in PRD §14 when discovery lands)
|
|
* ``locale`` — process-wide via ``Settings.raycast_locale`` because we
|
|
only spin up one ``raycast_api.Client`` per gateway
|
|
* ``system_instructions`` (wire) — that's a format marker, not content;
|
|
the SDK fills it from the source default and we let it
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from raycast_api import ( # noqa: F401 — UserPreferences re-exported for user configs
|
|
RemoteTool,
|
|
Source,
|
|
UserPreferences,
|
|
UserPreferencesArg,
|
|
)
|
|
|
|
from beaver_gateway.agents.base import BaseAgent
|
|
|
|
|
|
class RaycastAgent(BaseAgent):
|
|
"""Agent backed by ``raycast-api``.
|
|
|
|
``available_native_tools`` is the closed set of Raycast's server-side
|
|
"remote tools" (``web_search``, ``search_images``, ``read_page``) —
|
|
typed as ``RemoteTool`` so config-time IDE completion lists exactly
|
|
the three valid values. Pydantic also coerces string literals, so
|
|
``("web_search", "read_page")`` keeps working unchanged.
|
|
|
|
``user_preferences`` toggles the auto-generated ``<user-preferences>``
|
|
block Raycast prepends to ``additional_system_instructions``:
|
|
|
|
* ``True`` (default) → auto from host locale/timezone/today, rebuilt
|
|
every request so the date stays fresh;
|
|
* ``False`` → omit the block entirely;
|
|
* ``UserPreferences(...)`` instance → used verbatim (frozen at the
|
|
time the agent was loaded, so the date won't auto-update);
|
|
* ``Callable[[], UserPreferencesArg]`` → re-invoked on every request.
|
|
Use this for the common case "fresh date but custom
|
|
locale/timezone": ``user_preferences=lambda:
|
|
UserPreferences(locale="ru-RU", timezone="Europe/Berlin",
|
|
current_date=date.today().isoformat())``. Callables may nest
|
|
(a lambda returning a lambda…) but there's no real reason to.
|
|
|
|
The library uses this block for date/locale-aware formatting, not
|
|
for personalisation/memory — those are out of scope upstream.
|
|
|
|
``reasoning_effort`` values vary by model: GPT-5 takes
|
|
``"minimal"|"low"|"medium"|"high"``; Anthropic exposes nothing here
|
|
(Claude reasoning lives in a separate ``…-reasoning`` model variant
|
|
in the catalog). Unknown effort for the chosen model is ignored
|
|
server-side, so we stay loose as ``str | None``.
|
|
"""
|
|
|
|
streaming: bool = True
|
|
available_native_tools: tuple[RemoteTool, ...] = ()
|
|
source: Source = Source.AI_CHAT
|
|
|
|
temperature: float | None = None
|
|
reasoning_effort: str | None = None
|
|
tool_choice: str | None = None
|
|
user_preferences: UserPreferencesArg = True
|