feat: implement claude code backend
This commit is contained in:
+55
-3
@@ -4,20 +4,65 @@
|
||||
# ClaudeAgent, RaycastAgent, McpServer, ExposedMcp, Gateway already
|
||||
# bound — so importing them is optional. We import explicitly here so
|
||||
# IDEs and type-checkers see real symbols instead of free variables.
|
||||
import tempfile
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
from beaver_gateway.agents.base import ExposedMcp
|
||||
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
|
||||
from beaver_gateway.mcp.types import McpServer
|
||||
|
||||
|
||||
def current_time() -> str:
|
||||
"""Return the current local time as an ISO-8601 string.
|
||||
|
||||
Trivial demo tool for the Phase 2.1 internal MCP aggregator —
|
||||
confirms a ``python_tool`` namespace is reachable on
|
||||
``http://127.0.0.1:<INTERNAL_MCP_PORT>/mcp/time``.
|
||||
"""
|
||||
from datetime import datetime
|
||||
|
||||
return datetime.now().astimezone().isoformat()
|
||||
|
||||
gateway = Gateway(
|
||||
agents=[
|
||||
# Phase 2.2 — ClaudeCodeBackendAdapter routes this agent's
|
||||
# ``/v1/messages`` calls through ``claude-code-api``. The
|
||||
# ``time`` MCP gets exposed as ``mcp__time__current_time`` to
|
||||
# the subscription claude session via
|
||||
# ``BackendOptions.mcp_servers`` pointing at the internal
|
||||
# aggregator on ``127.0.0.1:INTERNAL_MCP_PORT/mcp/time/``.
|
||||
#
|
||||
# Fresh empty tempdir (not a hardcoded ``/tmp``) for two
|
||||
# reasons: claude-code-api derives the JSONL project-key from
|
||||
# ``cwd``, but claude itself writes the JSONL using the cwd's
|
||||
# realpath — on macOS ``/tmp`` and ``/var/folders/...`` are
|
||||
# both ``/private/...`` symlinks, so unresolved cwds make
|
||||
# ``JsonlWatcher`` time out waiting on the wrong path. The
|
||||
# explicit ``.resolve()`` collapses the symlink before claude
|
||||
# ever sees the dir, and ``mkdtemp`` guarantees the directory
|
||||
# is empty so claude does not pick up leftover files.
|
||||
ClaudeAgent(
|
||||
name="stub",
|
||||
model="claude-sonnet-4-6",
|
||||
system_prompt="You are a stub agent used to validate the Phase 0 skeleton.",
|
||||
cwd="/tmp",
|
||||
# ``system_prompt`` is appended to claude's built-in agent
|
||||
# prompt (via ``--append-system-prompt``) — so it adds the
|
||||
# agent's identity on top of claude-code's baseline tool
|
||||
# knowledge, rather than replacing it. Same shape as the
|
||||
# RaycastAgent's ``system_prompt → additional_system_instructions``
|
||||
# mapping. For full ``BackendOptions`` knobs (timeouts,
|
||||
# extra_args, history mode, etc.) import ``ClaudeCodeOptions``
|
||||
# and pass ``options=ClaudeCodeOptions(...)``.
|
||||
system_prompt=(
|
||||
"You are a stub agent used to validate the Phase 0 skeleton.\n"
|
||||
"If asked the current time, call the `current_time`"
|
||||
" MCP tool instead of guessing."
|
||||
),
|
||||
cwd=Path(tempfile.mkdtemp(prefix="beaver-stub-cwd-")).resolve(),
|
||||
expose_mcps=(ExposedMcp(name="time"),),
|
||||
),
|
||||
# Phase 1.2 — a RaycastAgent the AnthropicMessagesFrontend will
|
||||
# route via RaycastBackend. Phase 1.5 added the per-agent knobs
|
||||
@@ -45,7 +90,14 @@ gateway = Gateway(
|
||||
),
|
||||
),
|
||||
],
|
||||
mcps=[],
|
||||
mcps=[
|
||||
# Phase 2.1 — bundle of plain Python callables exposed as one
|
||||
# FastMCP namespace. The internal aggregator mounts it under
|
||||
# ``/mcp/time`` on ``127.0.0.1:INTERNAL_MCP_PORT``; Phase 2.2's
|
||||
# ClaudeCode adapter will forward that URL into
|
||||
# ``BackendOptions.mcp_servers``.
|
||||
McpServer.python_tool(name="time", tools=[current_time]),
|
||||
],
|
||||
frontends=[
|
||||
# Phase 1.4 — expose the agents as `model=<name>` on an
|
||||
# Anthropic-compatible Messages endpoint. Auth comes from
|
||||
|
||||
Reference in New Issue
Block a user