feat: add more logging
This commit is contained in:
@@ -27,6 +27,7 @@ agent's ``system_prompt`` is the canonical identity of the agent.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import uuid
|
import uuid
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import TYPE_CHECKING, Any, Self
|
from typing import TYPE_CHECKING, Any, Self
|
||||||
@@ -67,6 +68,9 @@ if TYPE_CHECKING:
|
|||||||
from beaver_gateway.core.events import MessageStreamEvent
|
from beaver_gateway.core.events import MessageStreamEvent
|
||||||
|
|
||||||
|
|
||||||
|
_log = logging.getLogger("beaver_gateway.backends.claude_code")
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["ClaudeCodeBackendAdapter", "TurnCapture"]
|
__all__ = ["ClaudeCodeBackendAdapter", "TurnCapture"]
|
||||||
|
|
||||||
|
|
||||||
@@ -257,12 +261,24 @@ class ClaudeCodeBackendAdapter:
|
|||||||
)
|
)
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
msgs_list: list[Mapping[str, Any]] = list(messages)
|
||||||
|
_log.info(
|
||||||
|
"complete: agent=%s n_messages=%d capture=%s live_sessions=%d",
|
||||||
|
agent.name,
|
||||||
|
len(msgs_list),
|
||||||
|
capture is not None,
|
||||||
|
self._backend.live_session_count,
|
||||||
|
)
|
||||||
|
|
||||||
message_id = f"msg_{uuid.uuid4().hex}"
|
message_id = f"msg_{uuid.uuid4().hex}"
|
||||||
yield build_message_start(message_id=message_id, model=agent.model)
|
yield build_message_start(message_id=message_id, model=agent.model)
|
||||||
|
|
||||||
next_index = 0
|
next_index = 0
|
||||||
stop_reason: str | None = None
|
stop_reason: str | None = None
|
||||||
usage: Mapping[str, Any] | None = None
|
usage: Mapping[str, Any] | None = None
|
||||||
|
n_text = 0
|
||||||
|
n_thinking = 0
|
||||||
|
n_tool_use = 0
|
||||||
# We keep raw events so we can hand them to
|
# We keep raw events so we can hand them to
|
||||||
# ``synthesize_turn_messages`` after the stream closes — the
|
# ``synthesize_turn_messages`` after the stream closes — the
|
||||||
# markdown frontend stores the result in its conversation
|
# markdown frontend stores the result in its conversation
|
||||||
@@ -271,10 +287,16 @@ class ClaudeCodeBackendAdapter:
|
|||||||
# are silently discarded from the wire but kept here.
|
# are silently discarded from the wire but kept here.
|
||||||
raw_events: list[Any] = []
|
raw_events: list[Any] = []
|
||||||
|
|
||||||
async for event in self._backend.complete(list(messages)):
|
async for event in self._backend.complete(msgs_list):
|
||||||
raw_events.append(event)
|
raw_events.append(event)
|
||||||
if isinstance(event, AssistantMessage):
|
if isinstance(event, AssistantMessage):
|
||||||
for block in event.content:
|
for block in event.content:
|
||||||
|
if isinstance(block, TextBlock):
|
||||||
|
n_text += 1
|
||||||
|
elif isinstance(block, ThinkingBlock):
|
||||||
|
n_thinking += 1
|
||||||
|
elif isinstance(block, ToolUseBlock):
|
||||||
|
n_tool_use += 1
|
||||||
for ev in _emit_block(block, next_index):
|
for ev in _emit_block(block, next_index):
|
||||||
yield ev
|
yield ev
|
||||||
next_index += 1
|
next_index += 1
|
||||||
@@ -298,6 +320,16 @@ class ClaudeCodeBackendAdapter:
|
|||||||
if capture is not None:
|
if capture is not None:
|
||||||
capture.synthesized_messages = synthesize_turn_messages(raw_events)
|
capture.synthesized_messages = synthesize_turn_messages(raw_events)
|
||||||
|
|
||||||
|
_log.info(
|
||||||
|
"complete: agent=%s DONE text=%d thinking=%d tool_use=%d stop=%s synth=%d",
|
||||||
|
agent.name,
|
||||||
|
n_text,
|
||||||
|
n_thinking,
|
||||||
|
n_tool_use,
|
||||||
|
stop_reason,
|
||||||
|
len(capture.synthesized_messages) if capture is not None else 0,
|
||||||
|
)
|
||||||
|
|
||||||
yield build_message_delta(
|
yield build_message_delta(
|
||||||
stop_reason=_map_stop_reason(stop_reason), usage=_normalize_usage(usage)
|
stop_reason=_map_stop_reason(stop_reason), usage=_normalize_usage(usage)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -571,7 +571,24 @@ class MarkdownFrontend(Frontend):
|
|||||||
conv, conv_external_id, stored_msgs = await self._resolve_conversation(
|
conv, conv_external_id, stored_msgs = await self._resolve_conversation(
|
||||||
runtime=runtime, metadata=parsed.metadata, agent_name=agent.name
|
runtime=runtime, metadata=parsed.metadata, agent_name=agent.name
|
||||||
)
|
)
|
||||||
|
_log.info(
|
||||||
|
"chat/stream: file=%s conv_external_id=%s conv_id=%d "
|
||||||
|
"stored_msgs=%d incoming_turns=%d",
|
||||||
|
filename,
|
||||||
|
conv_external_id,
|
||||||
|
conv.id or -1,
|
||||||
|
len(stored_msgs),
|
||||||
|
len(parsed.turns),
|
||||||
|
)
|
||||||
outcome = diff_and_fork(stored=stored_msgs, incoming=parsed.turns)
|
outcome = diff_and_fork(stored=stored_msgs, incoming=parsed.turns)
|
||||||
|
_log.info(
|
||||||
|
"chat/stream: file=%s diff_and_fork divergence=%s "
|
||||||
|
"backend_msgs=%d persist_msgs=%d",
|
||||||
|
filename,
|
||||||
|
outcome.divergence_index,
|
||||||
|
len(outcome.messages),
|
||||||
|
len(outcome.persist_messages),
|
||||||
|
)
|
||||||
capture: TurnCapture | None = (
|
capture: TurnCapture | None = (
|
||||||
TurnCapture() if isinstance(backend, ClaudeCodeBackendAdapter) else None
|
TurnCapture() if isinstance(backend, ClaudeCodeBackendAdapter) else None
|
||||||
)
|
)
|
||||||
@@ -579,6 +596,12 @@ class MarkdownFrontend(Frontend):
|
|||||||
kwargs: dict[str, Any] = {}
|
kwargs: dict[str, Any] = {}
|
||||||
if capture is not None:
|
if capture is not None:
|
||||||
kwargs["capture"] = capture
|
kwargs["capture"] = capture
|
||||||
|
_log.info(
|
||||||
|
"chat/stream: file=%s calling backend.complete agent=%s capture=%s",
|
||||||
|
filename,
|
||||||
|
agent.name,
|
||||||
|
capture is not None,
|
||||||
|
)
|
||||||
events = backend.complete(
|
events = backend.complete(
|
||||||
agent=agent, messages=outcome.messages, system=None, **kwargs
|
agent=agent, messages=outcome.messages, system=None, **kwargs
|
||||||
)
|
)
|
||||||
@@ -791,10 +814,30 @@ class MarkdownFrontend(Frontend):
|
|||||||
conv = await load_conversation(
|
conv = await load_conversation(
|
||||||
session, frontend="markdown", external_id=lookup_id
|
session, frontend="markdown", external_id=lookup_id
|
||||||
)
|
)
|
||||||
|
if conv is None:
|
||||||
|
_log.info(
|
||||||
|
"_resolve_conversation: frontmatter conv_id=%s "
|
||||||
|
"not found in DB, will mint new",
|
||||||
|
lookup_id,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_log.info(
|
||||||
|
"_resolve_conversation: LOADED existing conv "
|
||||||
|
"id=%d external_id=%s",
|
||||||
|
conv.id or -1,
|
||||||
|
conv.external_id,
|
||||||
|
)
|
||||||
if conv is None:
|
if conv is None:
|
||||||
conv = await mint_conversation(
|
conv = await mint_conversation(
|
||||||
session, frontend="markdown", agent_name=agent_name
|
session, frontend="markdown", agent_name=agent_name
|
||||||
)
|
)
|
||||||
|
_log.info(
|
||||||
|
"_resolve_conversation: MINTED new conv "
|
||||||
|
"id=%d external_id=%s agent=%s",
|
||||||
|
conv.id or -1,
|
||||||
|
conv.external_id,
|
||||||
|
agent_name,
|
||||||
|
)
|
||||||
if conv.id is None:
|
if conv.id is None:
|
||||||
msg = "conversation row missing primary key after commit"
|
msg = "conversation row missing primary key after commit"
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
@@ -824,10 +867,21 @@ class MarkdownFrontend(Frontend):
|
|||||||
else _fallback_synthesized(message)
|
else _fallback_synthesized(message)
|
||||||
)
|
)
|
||||||
canonical = [*persist_messages, new_user_msg, *synthesized]
|
canonical = [*persist_messages, new_user_msg, *synthesized]
|
||||||
|
_log.info(
|
||||||
|
"_persist_canonical_history: conv_id=%d writing %d msgs "
|
||||||
|
"(prior=%d + new_user + synth=%d)",
|
||||||
|
conversation_id,
|
||||||
|
len(canonical),
|
||||||
|
len(persist_messages),
|
||||||
|
len(synthesized),
|
||||||
|
)
|
||||||
async with runtime.db.session() as session:
|
async with runtime.db.session() as session:
|
||||||
await rewrite_messages(
|
await rewrite_messages(
|
||||||
session, conversation_id=conversation_id, messages=canonical
|
session, conversation_id=conversation_id, messages=canonical
|
||||||
)
|
)
|
||||||
|
_log.info(
|
||||||
|
"_persist_canonical_history: conv_id=%d DB committed", conversation_id
|
||||||
|
)
|
||||||
|
|
||||||
def _resolve_path(self, filename: str) -> Path:
|
def _resolve_path(self, filename: str) -> Path:
|
||||||
"""Resolve ``filename`` under the vault; reject escapes."""
|
"""Resolve ``filename`` under the vault; reject escapes."""
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ local = [
|
|||||||
{ name = "raycast-api", version = "0.1.0", source = { editable = "../raycast-api" } },
|
{ name = "raycast-api", version = "0.1.0", source = { editable = "../raycast-api" } },
|
||||||
]
|
]
|
||||||
prod = [
|
prod = [
|
||||||
{ name = "claude-code-api", version = "0.1.0", source = { git = "https://git.kotikot.com/beaver/claude-code-api.git#21dc26810b8241c2e317b1134042d5c96af0f7b1" } },
|
{ name = "claude-code-api", version = "0.1.0", source = { git = "https://git.kotikot.com/beaver/claude-code-api.git#d05c8dd613d94a03d9b3a2a4fb364ee3e15dada0" } },
|
||||||
{ name = "raycast-api", version = "0.1.0", source = { git = "https://git.kotikot.com/beaver/raycast-api.git#e73894c8e435da5c0709f92f69f11bcd0dab9afe" } },
|
{ name = "raycast-api", version = "0.1.0", source = { git = "https://git.kotikot.com/beaver/raycast-api.git#e73894c8e435da5c0709f92f69f11bcd0dab9afe" } },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -419,7 +419,7 @@ wheels = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "claude-code-api"
|
name = "claude-code-api"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = { git = "https://git.kotikot.com/beaver/claude-code-api.git#21dc26810b8241c2e317b1134042d5c96af0f7b1" }
|
source = { git = "https://git.kotikot.com/beaver/claude-code-api.git#d05c8dd613d94a03d9b3a2a4fb364ee3e15dada0" }
|
||||||
resolution-markers = [
|
resolution-markers = [
|
||||||
"python_full_version >= '3.14'",
|
"python_full_version >= '3.14'",
|
||||||
"python_full_version < '3.14'",
|
"python_full_version < '3.14'",
|
||||||
|
|||||||
Reference in New Issue
Block a user