feat(core): seeds without text wait for the first turn
This commit is contained in:
@@ -38,7 +38,7 @@ from claude_agent_sdk import (
|
||||
from sqlmodel import col, select
|
||||
|
||||
from beaver_gateway.core.injects import InjectQueue, inject_header
|
||||
from beaver_gateway.core.kinds import KINDS, Kind
|
||||
from beaver_gateway.core.kinds import KINDS, Kind, as_kind
|
||||
from beaver_gateway.core.transcript import (
|
||||
messages_from_entries,
|
||||
render_messages,
|
||||
@@ -492,7 +492,9 @@ class Conversations:
|
||||
``binding`` = ``(frontend, external_id)`` puts it into a window that
|
||||
already exists (a topic the user created) instead of asking the
|
||||
home frontend to ``materialize`` one. ``text`` rides with the seed
|
||||
as the first thing the user said, whatever the seed mode.
|
||||
as the first thing the user said, whatever the seed mode; without
|
||||
it the seed waits in ``flags`` and opens the first turn, so a fresh
|
||||
window stays silent and costs nothing until someone speaks.
|
||||
"""
|
||||
if seed not in SEEDS:
|
||||
msg = f"unknown seed {seed!r}"
|
||||
@@ -526,21 +528,41 @@ class Conversations:
|
||||
await self.bind(conv, frontend=binding[0], external_id=binding[1])
|
||||
else:
|
||||
await self.materialize(conv)
|
||||
prompt = await self._seed_text(
|
||||
SeedContext(
|
||||
kind=kind, seed=seed, agent=agent, parent=parent, text=text, title=title
|
||||
),
|
||||
window=window,
|
||||
ctx = SeedContext(
|
||||
kind=kind, seed=seed, agent=agent, parent=parent, text=text, title=title
|
||||
)
|
||||
if text is None:
|
||||
return await self.set_flags(conv, {"seed": seed, "seed_window": window})
|
||||
await self._queue.push(
|
||||
conversation_id=cast("int", conv.id),
|
||||
priority="user",
|
||||
origin=origin if text and seed != "brief" else f"сид:{seed}",
|
||||
text=prompt,
|
||||
origin=f"сид:{seed}" if seed == "brief" else origin,
|
||||
text=await self._seed_text(ctx, window=window),
|
||||
)
|
||||
self._ensure_worker(cast("int", conv.id))
|
||||
return conv
|
||||
|
||||
async def _pending_seed(self, conv: Conversation) -> str | None:
|
||||
"""A seed nobody has spoken after yet: rendered now, spent once."""
|
||||
seed = conv.flags.get("seed")
|
||||
if not seed:
|
||||
return None
|
||||
parent = await self.get_row(conv.parent_id) if conv.parent_id else None
|
||||
ctx = SeedContext(
|
||||
kind=as_kind(conv.kind),
|
||||
seed=str(seed),
|
||||
agent=conv.agent_name,
|
||||
parent=parent,
|
||||
text=None,
|
||||
title=conv.title,
|
||||
)
|
||||
window = conv.flags.get("seed_window")
|
||||
text = await self._seed_text(
|
||||
ctx, window=window if isinstance(window, int) else None
|
||||
)
|
||||
await self.set_flags(conv, {"seed": None, "seed_window": None})
|
||||
return text
|
||||
|
||||
async def fork(
|
||||
self,
|
||||
conv: Conversation,
|
||||
@@ -983,8 +1005,6 @@ class Conversations:
|
||||
stamp = datetime.now(UTC).astimezone().strftime("%Y-%m-%d %H:%M")
|
||||
title = f" «{ctx.title}»" if ctx.title else ""
|
||||
head = f"[сид: {ctx.seed}] {ctx.kind}{title}, {stamp}."
|
||||
if not ctx.text or ctx.seed == "brief":
|
||||
head += " Это контекст, не обращение: отвечать не нужно."
|
||||
body: str | None = None
|
||||
if self._texts.seed is not None:
|
||||
produced: Any = self._texts.seed(ctx)
|
||||
@@ -1065,6 +1085,9 @@ class Conversations:
|
||||
else:
|
||||
origin = "inject"
|
||||
prompt = "\n\n".join(f"{inject_header(i.origin)}\n{i.text}" for i in batch)
|
||||
seed = await self._pending_seed(conv)
|
||||
if seed:
|
||||
prompt = f"{seed}\n\n{prompt}"
|
||||
try:
|
||||
text, capture = await self.run_text_turn(
|
||||
conv, prompt, origin=origin, turn_id=turn_id, item_origin=head.origin
|
||||
|
||||
Reference in New Issue
Block a user