feat: implement raycast backend

This commit is contained in:
h
2026-05-19 21:06:01 +02:00
parent 221e660c5c
commit 757065f21c
16 changed files with 1415 additions and 31 deletions
+43 -6
View File
@@ -1,18 +1,55 @@
# Stub user config for the Phase 0 DoD.
# Sample user config — grows alongside the implementation phases.
#
# Loader (beaver_gateway/config_loader.py) execs this file with
# ClaudeAgent, RaycastAgent, McpServer, ExposedMcp, Gateway already
# bound. The top-level `gateway = Gateway(...)` is what gets picked up.
# bound — so importing them is optional. We import explicitly here so
# IDEs and type-checkers see real symbols instead of free variables.
from datetime import date
gateway = Gateway( # type: ignore[name-defined] # noqa: F821
from beaver_gateway.agents.claude import ClaudeAgent
from beaver_gateway.agents.raycast import RaycastAgent, RemoteTool, UserPreferences
from beaver_gateway.core.registry import Gateway
from beaver_gateway.frontends.anthropic import AnthropicMessagesFrontend
gateway = Gateway(
agents=[
ClaudeAgent( # type: ignore[name-defined] # noqa: F821
ClaudeAgent(
name="stub",
model="claude-sonnet-4-5",
model="claude-sonnet-4-6",
system_prompt="You are a stub agent used to validate the Phase 0 skeleton.",
cwd="/tmp",
),
# Phase 1.2 — a RaycastAgent the AnthropicMessagesFrontend will
# route via RaycastBackend. Phase 1.5 added the per-agent knobs
# (`temperature` / `additional_system_instructions` / etc.) —
# only `model`, `system_prompt`, and at least one of the others
# is mandatory.
RaycastAgent(
name="research",
model="Gemini 3.1 Flash Lite",
system_prompt=(
"You are a research assistant. "
"Reply in the user's language. Cite URLs when you use web search."
),
temperature=0.5,
available_native_tools=(RemoteTool.WEB_SEARCH, RemoteTool.READ_PAGE),
# Lambda so today's date is rebuilt on every request while
# locale/timezone stay pinned. ``True`` would give the same
# fresh-date behaviour but would also auto-pick host locale
# and timezone (``en-US`` / system tz), which isn't what we
# want here.
user_preferences=lambda: UserPreferences(
locale="en-GB",
timezone="Europe/Berlin",
current_date=date.today().isoformat(), # noqa: DTZ011 — local date is intended
),
),
],
mcps=[],
frontends=[],
frontends=[
# Phase 1.4 — expose the agents as `model=<name>` on an
# Anthropic-compatible Messages endpoint. Auth comes from
# `BOOTSTRAP_TOKENS` in the env (`name1:value1,name2:value2`).
AnthropicMessagesFrontend(host="0.0.0.0", port=8000),
],
)
+9
View File
@@ -16,5 +16,14 @@ services:
ADMIN_USER: "admin"
ADMIN_PASS: "change-me"
SESSION_SECRET: "dev-secret-change-me"
# Phase 1.4 — comma-separated `name:value` pairs. The frontend
# 401s every request until at least one token is set.
BOOTSTRAP_TOKENS: "cursor:dev-token-change-me"
# RAYCAST_BEARER / RAYCAST_DEVICE_ID + a raycast.json bind go
# here once you wire up an actual RaycastAgent. The example
# config.py declares one, so set these (or remove the agent)
# before exposing port 8000.
ports:
- "8000:8000"
volumes:
- ./config.py:/config/config.py:ro