feat(telegram): stop generation from the client, questions survive a restart, images reach the model inline, albums become one turn
This commit is contained in:
@@ -313,7 +313,7 @@ class ClaudeSdkBackend:
|
||||
if not history or history[-1].get("role") != "user":
|
||||
msg = "the last message must be a user turn"
|
||||
raise ValueError(msg)
|
||||
prompt = _prompt_text(history[-1].get("content"))
|
||||
prompt = _prompt(history[-1].get("content"))
|
||||
prior = history[:-1]
|
||||
key = conversation_id or fingerprint(prior)
|
||||
spec = _SessionSpec(kind=kind, pinned=pinned, tools=tools)
|
||||
@@ -404,7 +404,7 @@ class ClaudeSdkBackend:
|
||||
async def _run_turn(
|
||||
self,
|
||||
live: Session,
|
||||
prompt: str,
|
||||
prompt: str | list[dict[str, Any]],
|
||||
turn: _Turn,
|
||||
observer: Callable[[Any], None] | None = None,
|
||||
capture: TurnCapture | None = None,
|
||||
@@ -421,7 +421,7 @@ class ClaudeSdkBackend:
|
||||
raw: list[Any] = []
|
||||
next_index = 0
|
||||
offset = 0
|
||||
await live.client.query(prompt)
|
||||
await live.client.query(prompt if isinstance(prompt, str) else _stream(prompt))
|
||||
async for message in live.client.receive_response():
|
||||
if observer is not None:
|
||||
observer(message)
|
||||
@@ -845,14 +845,27 @@ def _mcp_disallowed(
|
||||
return out
|
||||
|
||||
|
||||
def _prompt_text(content: Any) -> str:
|
||||
def _prompt(content: Any) -> str | list[dict[str, Any]]:
|
||||
"""Plain text when the turn is text only; the block list when images ride along."""
|
||||
text = text_of(content)
|
||||
if not text:
|
||||
msg = "user message has no text content"
|
||||
raise ValueError(msg)
|
||||
if isinstance(content, list) and any(
|
||||
isinstance(b, dict) and b.get("type") != "text" for b in content
|
||||
):
|
||||
return [dict(b) for b in content if isinstance(b, dict)]
|
||||
return text
|
||||
|
||||
|
||||
async def _stream(content: list[dict[str, Any]]) -> AsyncIterator[dict[str, Any]]:
|
||||
yield {
|
||||
"type": "user",
|
||||
"message": {"role": "user", "content": content},
|
||||
"parent_tool_use_id": None,
|
||||
}
|
||||
|
||||
|
||||
def synthesize_turn_messages(raw: Iterable[Any]) -> list[dict[str, Any]]:
|
||||
out: list[dict[str, Any]] = []
|
||||
for message in raw:
|
||||
|
||||
@@ -20,7 +20,7 @@ from typing import TYPE_CHECKING, Any, Protocol
|
||||
import psutil
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import AsyncIterator, Iterator, Mapping
|
||||
from collections.abc import AsyncIterable, AsyncIterator, Iterator, Mapping
|
||||
|
||||
__all__ = ["DEFAULT_TTL", "Session", "SessionClient", "SessionPool", "cgroup_limit"]
|
||||
|
||||
@@ -41,7 +41,7 @@ _RSS_HEADROOM = 0.8
|
||||
|
||||
class SessionClient(Protocol):
|
||||
async def connect(self) -> None: ...
|
||||
async def query(self, prompt: str) -> None: ...
|
||||
async def query(self, prompt: str | AsyncIterable[dict[str, Any]]) -> None: ...
|
||||
def receive_response(self) -> AsyncIterator[Any]: ...
|
||||
async def interrupt(self) -> None: ...
|
||||
async def disconnect(self) -> None: ...
|
||||
|
||||
Reference in New Issue
Block a user